diff --git a/docs/acf-bukkit/allclasses-index.html b/docs/acf-bukkit/allclasses-index.html new file mode 100644 index 00000000..6ccdfa26 --- /dev/null +++ b/docs/acf-bukkit/allclasses-index.html @@ -0,0 +1,231 @@ + + + + + +All Classes (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
+ +
+
+
+

All Classes

+
+
+ +
+
+ + + diff --git a/docs/acf-bukkit/allclasses.html b/docs/acf-bukkit/allclasses.html new file mode 100644 index 00000000..81f2cb55 --- /dev/null +++ b/docs/acf-bukkit/allclasses.html @@ -0,0 +1,43 @@ + + + + + +All Classes (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + +

All Classes

+
+ +
+ + diff --git a/docs/acf-bukkit/allpackages-index.html b/docs/acf-bukkit/allpackages-index.html new file mode 100644 index 00000000..79f2a1da --- /dev/null +++ b/docs/acf-bukkit/allpackages-index.html @@ -0,0 +1,173 @@ + + + + + +All Packages (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
+ +
+
+
+

All Packages

+
+
+ +
+
+ + + diff --git a/docs/acf-bukkit/co/aikar/commands/ACFBukkitHelpTopic.html b/docs/acf-bukkit/co/aikar/commands/ACFBukkitHelpTopic.html index bd922d42..77a18d1a 100644 --- a/docs/acf-bukkit/co/aikar/commands/ACFBukkitHelpTopic.html +++ b/docs/acf-bukkit/co/aikar/commands/ACFBukkitHelpTopic.html @@ -1,12 +1,21 @@ - + - ACFBukkitHelpTopic (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
+ +
+
-
co.aikar.commands
+

Class ACFBukkitHelpTopic

@@ -196,38 +227,43 @@ extends org.bukkit.help.GenericCommandHelpTopic +
+ diff --git a/docs/acf-bukkit/co/aikar/commands/ACFBukkitUtil.html b/docs/acf-bukkit/co/aikar/commands/ACFBukkitUtil.html index 7a1b63af..03ce9d40 100644 --- a/docs/acf-bukkit/co/aikar/commands/ACFBukkitUtil.html +++ b/docs/acf-bukkit/co/aikar/commands/ACFBukkitUtil.html @@ -1,12 +1,21 @@ - + - ACFBukkitUtil (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
+ +
+
-
co.aikar.commands
+

Class ACFBukkitUtil

@@ -117,177 +140,210 @@ extends
  • +
    +
    +
    +
  • @@ -295,12 +351,13 @@ extends
  • +
  • +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/BukkitCommandCompletionContext.html b/docs/acf-bukkit/co/aikar/commands/BukkitCommandCompletionContext.html index 35d54fdd..cbfec1d7 100644 --- a/docs/acf-bukkit/co/aikar/commands/BukkitCommandCompletionContext.html +++ b/docs/acf-bukkit/co/aikar/commands/BukkitCommandCompletionContext.html @@ -1,12 +1,21 @@ - + - BukkitCommandCompletionContext (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BukkitCommandCompletionContext

    @@ -122,13 +145,14 @@ extends co.aikar.commands.CommandCompletionContext<
  • +
  • @@ -182,27 +212,28 @@ extends co.aikar.commands.CommandCompletionContext<
  • +
    +
  • + diff --git a/docs/acf-bukkit/co/aikar/commands/BukkitCommandContexts.html b/docs/acf-bukkit/co/aikar/commands/BukkitCommandContexts.html index 88d1fd52..3ec44af8 100644 --- a/docs/acf-bukkit/co/aikar/commands/BukkitCommandContexts.html +++ b/docs/acf-bukkit/co/aikar/commands/BukkitCommandContexts.html @@ -1,12 +1,21 @@ - + - BukkitCommandContexts (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BukkitCommandContexts

    @@ -116,13 +139,14 @@ extends co.aikar.commands.CommandContexts<
  • +
    +
    +
  • @@ -176,37 +207,42 @@ extends co.aikar.commands.CommandContexts<
  • +
    +
  • +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/BukkitCommandExecutionContext.html b/docs/acf-bukkit/co/aikar/commands/BukkitCommandExecutionContext.html index 3da476ff..5d4a1d37 100644 --- a/docs/acf-bukkit/co/aikar/commands/BukkitCommandExecutionContext.html +++ b/docs/acf-bukkit/co/aikar/commands/BukkitCommandExecutionContext.html @@ -1,12 +1,21 @@ - + - BukkitCommandExecutionContext (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BukkitCommandExecutionContext

    @@ -122,13 +145,14 @@ extends co.aikar.commands.CommandExecutionContext<
  • +
      -
    • +
    • Field Summary

        -
      • +
      • Fields inherited from class co.aikar.commands.CommandExecutionContext

        @@ -136,45 +160,51 @@ extends co.aikar.commands.CommandExecutionContext<
          -
        • +
        • Method Summary

          - +
          - + + - + - + +
          All Methods Instance Methods Concrete Methods 
          Modifier and TypeMethod and DescriptionMethodDescription
          org.bukkit.entity.PlayergetPlayer() +getPlayer()
          Returns the Player object if this Issuer is a Player
          org.bukkit.command.CommandSendergetSender() getSender() 
            -
          • +
          • Methods inherited from class co.aikar.commands.CommandExecutionContext

            canOverridePlayerContext, getAnnotation, getAnnotationValue, getAnnotationValue, getArgs, getBooleanFlagValue, getBooleanFlagValue, getCmd, getDoubleFlagValue, getFirstArg, getFlags, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFloatFlagValue, getIndex, getIntFlagValue, getIssuer, getLastArg, getLongFlagValue, getNumParams, getParam, getParameterPermissions, getPassedArgs, getResolvedArg, getResolvedArg, getResolvedArg, hasAnnotation, hasFlag, isLastArg, isOptional, joinArgs, joinArgs, popFirstArg, popLastArg
        +
  • @@ -182,27 +212,28 @@ extends co.aikar.commands.CommandExecutionContext<
  • +
    +
  • + diff --git a/docs/acf-bukkit/co/aikar/commands/BukkitConditionContext.html b/docs/acf-bukkit/co/aikar/commands/BukkitConditionContext.html index 3198e1e0..dd79afc8 100644 --- a/docs/acf-bukkit/co/aikar/commands/BukkitConditionContext.html +++ b/docs/acf-bukkit/co/aikar/commands/BukkitConditionContext.html @@ -1,12 +1,21 @@ - + - BukkitConditionContext (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BukkitConditionContext

    @@ -122,42 +145,47 @@ extends co.aikar.commands.ConditionContext<
  • +
    +
  • @@ -165,46 +193,51 @@ extends co.aikar.commands.ConditionContext<
  • +
      -
    • +
    • Method Detail

      - +
      • getSender

        -
        public org.bukkit.command.CommandSender getSender()
        +
        public org.bukkit.command.CommandSender getSender()
      - +
      • getPlayer

        -
        public org.bukkit.entity.Player getPlayer()
        +
        public org.bukkit.entity.Player getPlayer()
    +
  • +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/BukkitLocales.html b/docs/acf-bukkit/co/aikar/commands/BukkitLocales.html index ae0fbaad..1386afb9 100644 --- a/docs/acf-bukkit/co/aikar/commands/BukkitLocales.html +++ b/docs/acf-bukkit/co/aikar/commands/BukkitLocales.html @@ -1,12 +1,21 @@ - + - BukkitLocales (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BukkitLocales

    @@ -214,50 +250,53 @@ extends co.aikar.commands.Locales +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/BukkitMessageFormatter.html b/docs/acf-bukkit/co/aikar/commands/BukkitMessageFormatter.html index 834667c3..54da868b 100644 --- a/docs/acf-bukkit/co/aikar/commands/BukkitMessageFormatter.html +++ b/docs/acf-bukkit/co/aikar/commands/BukkitMessageFormatter.html @@ -1,12 +1,21 @@ - + - BukkitMessageFormatter (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BukkitMessageFormatter

    @@ -161,37 +190,42 @@ extends co.aikar.commands.MessageFormatter<org.bukkit.ChatColor> +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/BukkitRegisteredCommand.html b/docs/acf-bukkit/co/aikar/commands/BukkitRegisteredCommand.html index 22ce5735..d14f2992 100644 --- a/docs/acf-bukkit/co/aikar/commands/BukkitRegisteredCommand.html +++ b/docs/acf-bukkit/co/aikar/commands/BukkitRegisteredCommand.html @@ -1,12 +1,21 @@ - + - BukkitRegisteredCommand (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BukkitRegisteredCommand

    @@ -122,13 +145,14 @@ extends co.aikar.commands.RegisteredCommand<
  • +
  • @@ -180,54 +210,59 @@ extends co.aikar.commands.RegisteredCommand<
  • +
    +
  • +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/BukkitRootCommand.html b/docs/acf-bukkit/co/aikar/commands/BukkitRootCommand.html index f504a341..5181b604 100644 --- a/docs/acf-bukkit/co/aikar/commands/BukkitRootCommand.html +++ b/docs/acf-bukkit/co/aikar/commands/BukkitRootCommand.html @@ -1,12 +1,21 @@ - + - BukkitRootCommand (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BukkitRootCommand

    @@ -228,18 +266,19 @@ implements co.aikar.commands.RootCommand +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/MinecraftMessageKeys.html b/docs/acf-bukkit/co/aikar/commands/MinecraftMessageKeys.html index 08b4bdc5..5c86dcff 100644 --- a/docs/acf-bukkit/co/aikar/commands/MinecraftMessageKeys.html +++ b/docs/acf-bukkit/co/aikar/commands/MinecraftMessageKeys.html @@ -1,12 +1,21 @@ - + - MinecraftMessageKeys (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Enum MinecraftMessageKeys

    @@ -229,136 +273,139 @@ the order they are declared. +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/OnlinePlayer.html b/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/OnlinePlayer.html index d2226802..0e8bc73b 100644 --- a/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/OnlinePlayer.html +++ b/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - OnlinePlayer (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands.bukkit.contexts
    +

    Class OnlinePlayer

    @@ -121,79 +144,94 @@ extends
  • +
      -
    • +
    • Field Summary

      - +
      - + + - + +
      Fields 
      Modifier and TypeField and DescriptionFieldDescription
      org.bukkit.entity.Playerplayer player 
    +
    +
      -
    • +
    • Constructor Summary

      - +
      - + + - + +
      Constructors 
      Constructor and DescriptionConstructorDescription
      OnlinePlayer(org.bukkit.entity.Player player) OnlinePlayer​(org.bukkit.entity.Player player) 
    +
    +
    +
  • @@ -201,12 +239,13 @@ extends
  • +
      -
    • +
    • Field Detail

      - +
        @@ -217,94 +256,102 @@ extends +
    +
    +
  • +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/class-use/OnlinePlayer.html b/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/class-use/OnlinePlayer.html index bddf4b5b..f29368d3 100644 --- a/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/class-use/OnlinePlayer.html +++ b/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/class-use/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.bukkit.contexts.OnlinePlayer (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.bukkit.contexts.OnlinePlayer

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/package-summary.html b/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/package-summary.html index 83ab4d29..1dd5b6bb 100644 --- a/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/package-summary.html +++ b/docs/acf-bukkit/co/aikar/commands/bukkit/contexts/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.bukkit.contexts (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Package co.aikar.commands.bukkit.contexts

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/ACFBukkitHelpTopic.html b/docs/acf-bukkit/co/aikar/commands/class-use/ACFBukkitHelpTopic.html index 5d34df98..0381111a 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/ACFBukkitHelpTopic.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/ACFBukkitHelpTopic.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ACFBukkitHelpTopic (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.ACFBukkitHelpTopic

    No usage of co.aikar.commands.ACFBukkitHelpTopic
    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/ACFBukkitUtil.html b/docs/acf-bukkit/co/aikar/commands/class-use/ACFBukkitUtil.html index bdad89f8..2428538d 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/ACFBukkitUtil.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/ACFBukkitUtil.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ACFBukkitUtil (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.ACFBukkitUtil

    No usage of co.aikar.commands.ACFBukkitUtil
    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandCompletionContext.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandCompletionContext.html index 5cbdd535..a887a98d 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandCompletionContext.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandCompletionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitCommandCompletionContext (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitCommandCompletionContext

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandCompletions.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandCompletions.html index fc5b1970..7bc92ac9 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandCompletions.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandCompletions.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitCommandCompletions (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitCommandCompletions

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandContexts.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandContexts.html index ba6a2118..14ed4a89 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandContexts.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandContexts.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitCommandContexts (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitCommandContexts

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandExecutionContext.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandExecutionContext.html index 21e25a5f..6ee235f1 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandExecutionContext.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandExecutionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitCommandExecutionContext (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitCommandExecutionContext

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandIssuer.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandIssuer.html index e840f5ce..e184d429 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandIssuer.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandIssuer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitCommandIssuer (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitCommandIssuer

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandManager.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandManager.html index 1876c207..0b9479ff 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandManager.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitCommandManager.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitCommandManager (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitCommandManager

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitConditionContext.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitConditionContext.html index b275513b..d99240d6 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitConditionContext.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitConditionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitConditionContext (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitConditionContext

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitLocales.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitLocales.html index 7d5f4f31..8044476f 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitLocales.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitLocales.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitLocales (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitLocales

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitMessageFormatter.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitMessageFormatter.html index 91bc161b..6dac88ed 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitMessageFormatter.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitMessageFormatter.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitMessageFormatter (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitMessageFormatter

    No usage of co.aikar.commands.BukkitMessageFormatter
    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitRegisteredCommand.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitRegisteredCommand.html index e541b0ba..256967b8 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitRegisteredCommand.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitRegisteredCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitRegisteredCommand (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitRegisteredCommand

    No usage of co.aikar.commands.BukkitRegisteredCommand
    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitRootCommand.html b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitRootCommand.html index 629d7fb1..42740a21 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/BukkitRootCommand.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/BukkitRootCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BukkitRootCommand (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BukkitRootCommand

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/class-use/MinecraftMessageKeys.html b/docs/acf-bukkit/co/aikar/commands/class-use/MinecraftMessageKeys.html index 5187bc3a..7be826f2 100644 --- a/docs/acf-bukkit/co/aikar/commands/class-use/MinecraftMessageKeys.html +++ b/docs/acf-bukkit/co/aikar/commands/class-use/MinecraftMessageKeys.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.MinecraftMessageKeys (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.MinecraftMessageKeys

    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/contexts/OnlinePlayer.html b/docs/acf-bukkit/co/aikar/commands/contexts/OnlinePlayer.html index 69a1bb41..2987f54b 100644 --- a/docs/acf-bukkit/co/aikar/commands/contexts/OnlinePlayer.html +++ b/docs/acf-bukkit/co/aikar/commands/contexts/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - OnlinePlayer (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands.contexts
    +

    Class OnlinePlayer

    @@ -120,61 +143,69 @@ extends
  • +
    +
    +
      -
    • +
    • Constructor Summary

      - +
      - + + - +
      Constructors 
      Constructor and DescriptionConstructorDescription
      OnlinePlayer(org.bukkit.entity.Player player) -
      Deprecated. 
      +
      OnlinePlayer​(org.bukkit.entity.Player player) +
      Deprecated.
       
    +
    +
    +
  • @@ -182,38 +213,43 @@ extends
  • +
      -
    • +
    • Constructor Detail

      - +
      • OnlinePlayer

        -
        public OnlinePlayer(org.bukkit.entity.Player player)
        -
        Deprecated. 
        +
        public OnlinePlayer​(org.bukkit.entity.Player player)
        +
        Deprecated.
    +
  • +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/contexts/class-use/OnlinePlayer.html b/docs/acf-bukkit/co/aikar/commands/contexts/class-use/OnlinePlayer.html index 3cf343e9..c37be575 100644 --- a/docs/acf-bukkit/co/aikar/commands/contexts/class-use/OnlinePlayer.html +++ b/docs/acf-bukkit/co/aikar/commands/contexts/class-use/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.contexts.OnlinePlayer (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.contexts.OnlinePlayer

    No usage of co.aikar.commands.contexts.OnlinePlayer
    +
    + diff --git a/docs/acf-bukkit/co/aikar/commands/contexts/package-summary.html b/docs/acf-bukkit/co/aikar/commands/contexts/package-summary.html index e1f631e3..d0305ac8 100644 --- a/docs/acf-bukkit/co/aikar/commands/contexts/package-summary.html +++ b/docs/acf-bukkit/co/aikar/commands/contexts/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.contexts (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Package co.aikar.commands.contexts

    +
    + diff --git a/docs/acf-bukkit/constant-values.html b/docs/acf-bukkit/constant-values.html index 1d8f224f..bfd07ce1 100644 --- a/docs/acf-bukkit/constant-values.html +++ b/docs/acf-bukkit/constant-values.html @@ -1,12 +1,21 @@ - + - Constant Field Values (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Constant Field Values

    +

    Contents

    +
    +
    + diff --git a/docs/acf-bukkit/deprecated-list.html b/docs/acf-bukkit/deprecated-list.html index b98d4110..3e5b251c 100644 --- a/docs/acf-bukkit/deprecated-list.html +++ b/docs/acf-bukkit/deprecated-list.html @@ -1,12 +1,21 @@ - + - Deprecated List (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Deprecated API

    Contents

    -
    +
    - +
    +
    + + diff --git a/docs/acf-bukkit/jquery/external/jquery/jquery.js b/docs/acf-bukkit/jquery/external/jquery/jquery.js new file mode 100644 index 00000000..9b5206bc --- /dev/null +++ b/docs/acf-bukkit/jquery/external/jquery/jquery.js @@ -0,0 +1,10364 @@ +/*! + * jQuery JavaScript Library v3.3.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2018-01-20T17:24Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + + + + var preservedScriptAttributes = { + type: true, + src: true, + noModule: true + }; + + function DOMEval( code, doc, node ) { + doc = doc || document; + + var i, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + if ( node[ i ] ) { + script[ i ] = node[ i ]; + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.3.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && Array.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( nodeName( elem, "iframe" ) ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
    " ], + col: [ 2, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + div.style.position = "absolute"; + scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a property mapped along what jQuery.cssProps suggests or to +// a vendor prefixed property. +function finalPropName( name ) { + var ret = jQuery.cssProps[ name ]; + if ( !ret ) { + ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + } + return ret; +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + ) ); + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + val = curCSS( elem, dimension, styles ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox; + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = valueIsBorderBox && + ( support.boxSizingReliable() || val === elem.style[ dimension ] ); + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + if ( val === "auto" || + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { + + val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; + + // offsetWidth/offsetHeight provide border-box values + valueIsBorderBox = true; + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra && boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ); + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && support.scrollboxSize() === styles.position ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = Date.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "\r\n"; + +// inject VBScript +document.write(IEBinaryToArray_ByteStr_Script); + +global.JSZipUtils._getBinaryFromXHR = function (xhr) { + var binary = xhr.responseBody; + var byteMapping = {}; + for ( var i = 0; i < 256; i++ ) { + for ( var j = 0; j < 256; j++ ) { + byteMapping[ String.fromCharCode( i + (j << 8) ) ] = + String.fromCharCode(i) + String.fromCharCode(j); + } + } + var rawBytes = IEBinaryToArray_ByteStr(binary); + var lastChr = IEBinaryToArray_ByteStr_Last(binary); + return rawBytes.replace(/[\s\S]/g, function( match ) { + return byteMapping[match]; + }) + lastChr; +}; + +// enforcing Stuk's coding style +// vim: set shiftwidth=4 softtabstop=4: + +},{}]},{},[1]) +; diff --git a/docs/acf-bukkit/jquery/jszip-utils/dist/jszip-utils-ie.min.js b/docs/acf-bukkit/jquery/jszip-utils/dist/jszip-utils-ie.min.js new file mode 100644 index 00000000..93d8bc8e --- /dev/null +++ b/docs/acf-bukkit/jquery/jszip-utils/dist/jszip-utils-ie.min.js @@ -0,0 +1,10 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); diff --git a/docs/acf-bukkit/jquery/jszip-utils/dist/jszip-utils.js b/docs/acf-bukkit/jquery/jszip-utils/dist/jszip-utils.js new file mode 100644 index 00000000..775895ec --- /dev/null +++ b/docs/acf-bukkit/jquery/jszip-utils/dist/jszip-utils.js @@ -0,0 +1,118 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ + +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64; + enc4 = remainingBytes > 2 ? (chr3 & 63) : 64; + + output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4)); + + } + + return output.join(""); +}; + +// public method for decoding +exports.decode = function(input) { + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0, resultIndex = 0; + + var dataUrlPrefix = "data:"; + + if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) { + // This is a common error: people give a data url + // (data:image/png;base64,iVBOR...) with a {base64: true} and + // wonders why things don't work. + // We can detect that the string input looks like a data url but we + // *can't* be sure it is one: removing everything up to the comma would + // be too dangerous. + throw new Error("Invalid base64 input, it looks like a data url."); + } + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + var totalLength = input.length * 3 / 4; + if(input.charAt(input.length - 1) === _keyStr.charAt(64)) { + totalLength--; + } + if(input.charAt(input.length - 2) === _keyStr.charAt(64)) { + totalLength--; + } + if (totalLength % 1 !== 0) { + // totalLength is not an integer, the length does not match a valid + // base64 content. That can happen if: + // - the input is not a base64 content + // - the input is *almost* a base64 content, with a extra chars at the + // beginning or at the end + // - the input uses a base64 variant (base64url for example) + throw new Error("Invalid base64 input, bad content length."); + } + var output; + if (support.uint8array) { + output = new Uint8Array(totalLength|0); + } else { + output = new Array(totalLength|0); + } + + while (i < input.length) { + + enc1 = _keyStr.indexOf(input.charAt(i++)); + enc2 = _keyStr.indexOf(input.charAt(i++)); + enc3 = _keyStr.indexOf(input.charAt(i++)); + enc4 = _keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output[resultIndex++] = chr1; + + if (enc3 !== 64) { + output[resultIndex++] = chr2; + } + if (enc4 !== 64) { + output[resultIndex++] = chr3; + } + + } + + return output; +}; + +},{"./support":30,"./utils":32}],2:[function(require,module,exports){ +'use strict'; + +var external = require("./external"); +var DataWorker = require('./stream/DataWorker'); +var DataLengthProbe = require('./stream/DataLengthProbe'); +var Crc32Probe = require('./stream/Crc32Probe'); +var DataLengthProbe = require('./stream/DataLengthProbe'); + +/** + * Represent a compressed object, with everything needed to decompress it. + * @constructor + * @param {number} compressedSize the size of the data compressed. + * @param {number} uncompressedSize the size of the data after decompression. + * @param {number} crc32 the crc32 of the decompressed file. + * @param {object} compression the type of compression, see lib/compressions.js. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data. + */ +function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) { + this.compressedSize = compressedSize; + this.uncompressedSize = uncompressedSize; + this.crc32 = crc32; + this.compression = compression; + this.compressedContent = data; +} + +CompressedObject.prototype = { + /** + * Create a worker to get the uncompressed content. + * @return {GenericWorker} the worker. + */ + getContentWorker : function () { + var worker = new DataWorker(external.Promise.resolve(this.compressedContent)) + .pipe(this.compression.uncompressWorker()) + .pipe(new DataLengthProbe("data_length")); + + var that = this; + worker.on("end", function () { + if(this.streamInfo['data_length'] !== that.uncompressedSize) { + throw new Error("Bug : uncompressed data size mismatch"); + } + }); + return worker; + }, + /** + * Create a worker to get the compressed content. + * @return {GenericWorker} the worker. + */ + getCompressedWorker : function () { + return new DataWorker(external.Promise.resolve(this.compressedContent)) + .withStreamInfo("compressedSize", this.compressedSize) + .withStreamInfo("uncompressedSize", this.uncompressedSize) + .withStreamInfo("crc32", this.crc32) + .withStreamInfo("compression", this.compression) + ; + } +}; + +/** + * Chain the given worker with other workers to compress the content with the + * given compresion. + * @param {GenericWorker} uncompressedWorker the worker to pipe. + * @param {Object} compression the compression object. + * @param {Object} compressionOptions the options to use when compressing. + * @return {GenericWorker} the new worker compressing the content. + */ +CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions) { + return uncompressedWorker + .pipe(new Crc32Probe()) + .pipe(new DataLengthProbe("uncompressedSize")) + .pipe(compression.compressWorker(compressionOptions)) + .pipe(new DataLengthProbe("compressedSize")) + .withStreamInfo("compression", compression); +}; + +module.exports = CompressedObject; + +},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require("./stream/GenericWorker"); + +exports.STORE = { + magic: "\x00\x00", + compressWorker : function (compressionOptions) { + return new GenericWorker("STORE compression"); + }, + uncompressWorker : function () { + return new GenericWorker("STORE decompression"); + } +}; +exports.DEFLATE = require('./flate'); + +},{"./flate":7,"./stream/GenericWorker":28}],4:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); + +/** + * The following functions come from pako, from pako/lib/zlib/crc32.js + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +// That's all for the pako functions. + +/** + * Compute the crc32 of a string. + * This is almost the same as the function crc32, but for strings. Using the + * same function for the two use cases leads to horrible performances. + * @param {Number} crc the starting value of the crc. + * @param {String} str the string to use. + * @param {Number} len the length of the string. + * @param {Number} pos the starting position for the crc32 computation. + * @return {Number} the computed crc32. + */ +function crc32str(crc, str, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +module.exports = function crc32wrapper(input, crc) { + if (typeof input === "undefined" || !input.length) { + return 0; + } + + var isArray = utils.getTypeOf(input) !== "string"; + + if(isArray) { + return crc32(crc|0, input, input.length, 0); + } else { + return crc32str(crc|0, input, input.length, 0); + } +}; + +},{"./utils":32}],5:[function(require,module,exports){ +'use strict'; +exports.base64 = false; +exports.binary = false; +exports.dir = false; +exports.createFolders = true; +exports.date = null; +exports.compression = null; +exports.compressionOptions = null; +exports.comment = null; +exports.unixPermissions = null; +exports.dosPermissions = null; + +},{}],6:[function(require,module,exports){ +/* global Promise */ +'use strict'; + +// load the global object first: +// - it should be better integrated in the system (unhandledRejection in node) +// - the environment may have a custom Promise implementation (see zone.js) +var ES6Promise = null; +if (typeof Promise !== "undefined") { + ES6Promise = Promise; +} else { + ES6Promise = require("lie"); +} + +/** + * Let the user use/change some implementations. + */ +module.exports = { + Promise: ES6Promise +}; + +},{"lie":58}],7:[function(require,module,exports){ +'use strict'; +var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); + +var pako = require("pako"); +var utils = require("./utils"); +var GenericWorker = require("./stream/GenericWorker"); + +var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array"; + +exports.magic = "\x08\x00"; + +/** + * Create a worker that uses pako to inflate/deflate. + * @constructor + * @param {String} action the name of the pako function to call : either "Deflate" or "Inflate". + * @param {Object} options the options to use when (de)compressing. + */ +function FlateWorker(action, options) { + GenericWorker.call(this, "FlateWorker/" + action); + + this._pako = null; + this._pakoAction = action; + this._pakoOptions = options; + // the `meta` object from the last chunk received + // this allow this worker to pass around metadata + this.meta = {}; +} + +utils.inherits(FlateWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +FlateWorker.prototype.processChunk = function (chunk) { + this.meta = chunk.meta; + if (this._pako === null) { + this._createPako(); + } + this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false); +}; + +/** + * @see GenericWorker.flush + */ +FlateWorker.prototype.flush = function () { + GenericWorker.prototype.flush.call(this); + if (this._pako === null) { + this._createPako(); + } + this._pako.push([], true); +}; +/** + * @see GenericWorker.cleanUp + */ +FlateWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this._pako = null; +}; + +/** + * Create the _pako object. + * TODO: lazy-loading this object isn't the best solution but it's the + * quickest. The best solution is to lazy-load the worker list. See also the + * issue #446. + */ +FlateWorker.prototype._createPako = function () { + this._pako = new pako[this._pakoAction]({ + raw: true, + level: this._pakoOptions.level || -1 // default compression + }); + var self = this; + this._pako.onData = function(data) { + self.push({ + data : data, + meta : self.meta + }); + }; +}; + +exports.compressWorker = function (compressionOptions) { + return new FlateWorker("Deflate", compressionOptions); +}; +exports.uncompressWorker = function () { + return new FlateWorker("Inflate", {}); +}; + +},{"./stream/GenericWorker":28,"./utils":32,"pako":59}],8:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); +var utf8 = require('../utf8'); +var crc32 = require('../crc32'); +var signature = require('../signature'); + +/** + * Transform an integer into a string in hexadecimal. + * @private + * @param {number} dec the number to convert. + * @param {number} bytes the number of bytes to generate. + * @returns {string} the result. + */ +var decToHex = function(dec, bytes) { + var hex = "", i; + for (i = 0; i < bytes; i++) { + hex += String.fromCharCode(dec & 0xff); + dec = dec >>> 8; + } + return hex; +}; + +/** + * Generate the UNIX part of the external file attributes. + * @param {Object} unixPermissions the unix permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : + * + * TTTTsstrwxrwxrwx0000000000ADVSHR + * ^^^^____________________________ file type, see zipinfo.c (UNX_*) + * ^^^_________________________ setuid, setgid, sticky + * ^^^^^^^^^________________ permissions + * ^^^^^^^^^^______ not used ? + * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only + */ +var generateUnixExternalFileAttr = function (unixPermissions, isDir) { + + var result = unixPermissions; + if (!unixPermissions) { + // I can't use octal values in strict mode, hence the hexa. + // 040775 => 0x41fd + // 0100664 => 0x81b4 + result = isDir ? 0x41fd : 0x81b4; + } + return (result & 0xFFFF) << 16; +}; + +/** + * Generate the DOS part of the external file attributes. + * @param {Object} dosPermissions the dos permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * Bit 0 Read-Only + * Bit 1 Hidden + * Bit 2 System + * Bit 3 Volume Label + * Bit 4 Directory + * Bit 5 Archive + */ +var generateDosExternalFileAttr = function (dosPermissions, isDir) { + + // the dir flag is already set for compatibility + return (dosPermissions || 0) & 0x3F; +}; + +/** + * Generate the various parts used in the construction of the final zip file. + * @param {Object} streamInfo the hash with informations about the compressed file. + * @param {Boolean} streamedContent is the content streamed ? + * @param {Boolean} streamingEnded is the stream finished ? + * @param {number} offset the current offset from the start of the zip file. + * @param {String} platform let's pretend we are this platform (change platform dependents fields) + * @param {Function} encodeFileName the function to encode the file name / comment. + * @return {Object} the zip parts. + */ +var generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) { + var file = streamInfo['file'], + compression = streamInfo['compression'], + useCustomEncoding = encodeFileName !== utf8.utf8encode, + encodedFileName = utils.transformTo("string", encodeFileName(file.name)), + utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), + comment = file.comment, + encodedComment = utils.transformTo("string", encodeFileName(comment)), + utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), + useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, + useUTF8ForComment = utfEncodedComment.length !== comment.length, + dosTime, + dosDate, + extraFields = "", + unicodePathExtraField = "", + unicodeCommentExtraField = "", + dir = file.dir, + date = file.date; + + + var dataInfo = { + crc32 : 0, + compressedSize : 0, + uncompressedSize : 0 + }; + + // if the content is streamed, the sizes/crc32 are only available AFTER + // the end of the stream. + if (!streamedContent || streamingEnded) { + dataInfo.crc32 = streamInfo['crc32']; + dataInfo.compressedSize = streamInfo['compressedSize']; + dataInfo.uncompressedSize = streamInfo['uncompressedSize']; + } + + var bitflag = 0; + if (streamedContent) { + // Bit 3: the sizes/crc32 are set to zero in the local header. + // The correct values are put in the data descriptor immediately + // following the compressed data. + bitflag |= 0x0008; + } + if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) { + // Bit 11: Language encoding flag (EFS). + bitflag |= 0x0800; + } + + + var extFileAttr = 0; + var versionMadeBy = 0; + if (dir) { + // dos or unix, we set the dos dir flag + extFileAttr |= 0x00010; + } + if(platform === "UNIX") { + versionMadeBy = 0x031E; // UNIX, version 3.0 + extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); + } else { // DOS or other, fallback to DOS + versionMadeBy = 0x0014; // DOS, version 2.0 + extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); + } + + // date + // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html + + dosTime = date.getUTCHours(); + dosTime = dosTime << 6; + dosTime = dosTime | date.getUTCMinutes(); + dosTime = dosTime << 5; + dosTime = dosTime | date.getUTCSeconds() / 2; + + dosDate = date.getUTCFullYear() - 1980; + dosDate = dosDate << 4; + dosDate = dosDate | (date.getUTCMonth() + 1); + dosDate = dosDate << 5; + dosDate = dosDate | date.getUTCDate(); + + if (useUTF8ForFileName) { + // set the unicode path extra field. unzip needs at least one extra + // field to correctly handle unicode path, so using the path is as good + // as any other information. This could improve the situation with + // other archive managers too. + // This field is usually used without the utf8 flag, with a non + // unicode path in the header (winrar, winzip). This helps (a bit) + // with the messy Windows' default compressed folders feature but + // breaks on p7zip which doesn't seek the unicode path extra field. + // So for now, UTF-8 everywhere ! + unicodePathExtraField = + // Version + decToHex(1, 1) + + // NameCRC32 + decToHex(crc32(encodedFileName), 4) + + // UnicodeName + utfEncodedFileName; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x70" + + // size + decToHex(unicodePathExtraField.length, 2) + + // content + unicodePathExtraField; + } + + if(useUTF8ForComment) { + + unicodeCommentExtraField = + // Version + decToHex(1, 1) + + // CommentCRC32 + decToHex(crc32(encodedComment), 4) + + // UnicodeName + utfEncodedComment; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x63" + + // size + decToHex(unicodeCommentExtraField.length, 2) + + // content + unicodeCommentExtraField; + } + + var header = ""; + + // version needed to extract + header += "\x0A\x00"; + // general purpose bit flag + header += decToHex(bitflag, 2); + // compression method + header += compression.magic; + // last mod file time + header += decToHex(dosTime, 2); + // last mod file date + header += decToHex(dosDate, 2); + // crc-32 + header += decToHex(dataInfo.crc32, 4); + // compressed size + header += decToHex(dataInfo.compressedSize, 4); + // uncompressed size + header += decToHex(dataInfo.uncompressedSize, 4); + // file name length + header += decToHex(encodedFileName.length, 2); + // extra field length + header += decToHex(extraFields.length, 2); + + + var fileRecord = signature.LOCAL_FILE_HEADER + header + encodedFileName + extraFields; + + var dirRecord = signature.CENTRAL_FILE_HEADER + + // version made by (00: DOS) + decToHex(versionMadeBy, 2) + + // file header (common to file and central directory) + header + + // file comment length + decToHex(encodedComment.length, 2) + + // disk number start + "\x00\x00" + + // internal file attributes TODO + "\x00\x00" + + // external file attributes + decToHex(extFileAttr, 4) + + // relative offset of local header + decToHex(offset, 4) + + // file name + encodedFileName + + // extra field + extraFields + + // file comment + encodedComment; + + return { + fileRecord: fileRecord, + dirRecord: dirRecord + }; +}; + +/** + * Generate the EOCD record. + * @param {Number} entriesCount the number of entries in the zip file. + * @param {Number} centralDirLength the length (in bytes) of the central dir. + * @param {Number} localDirLength the length (in bytes) of the local dir. + * @param {String} comment the zip file comment as a binary string. + * @param {Function} encodeFileName the function to encode the comment. + * @return {String} the EOCD record. + */ +var generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) { + var dirEnd = ""; + var encodedComment = utils.transformTo("string", encodeFileName(comment)); + + // end of central dir signature + dirEnd = signature.CENTRAL_DIRECTORY_END + + // number of this disk + "\x00\x00" + + // number of the disk with the start of the central directory + "\x00\x00" + + // total number of entries in the central directory on this disk + decToHex(entriesCount, 2) + + // total number of entries in the central directory + decToHex(entriesCount, 2) + + // size of the central directory 4 bytes + decToHex(centralDirLength, 4) + + // offset of start of central directory with respect to the starting disk number + decToHex(localDirLength, 4) + + // .ZIP file comment length + decToHex(encodedComment.length, 2) + + // .ZIP file comment + encodedComment; + + return dirEnd; +}; + +/** + * Generate data descriptors for a file entry. + * @param {Object} streamInfo the hash generated by a worker, containing informations + * on the file entry. + * @return {String} the data descriptors. + */ +var generateDataDescriptors = function (streamInfo) { + var descriptor = ""; + descriptor = signature.DATA_DESCRIPTOR + + // crc-32 4 bytes + decToHex(streamInfo['crc32'], 4) + + // compressed size 4 bytes + decToHex(streamInfo['compressedSize'], 4) + + // uncompressed size 4 bytes + decToHex(streamInfo['uncompressedSize'], 4); + + return descriptor; +}; + + +/** + * A worker to concatenate other workers to create a zip file. + * @param {Boolean} streamFiles `true` to stream the content of the files, + * `false` to accumulate it. + * @param {String} comment the comment to use. + * @param {String} platform the platform to use, "UNIX" or "DOS". + * @param {Function} encodeFileName the function to encode file names and comments. + */ +function ZipFileWorker(streamFiles, comment, platform, encodeFileName) { + GenericWorker.call(this, "ZipFileWorker"); + // The number of bytes written so far. This doesn't count accumulated chunks. + this.bytesWritten = 0; + // The comment of the zip file + this.zipComment = comment; + // The platform "generating" the zip file. + this.zipPlatform = platform; + // the function to encode file names and comments. + this.encodeFileName = encodeFileName; + // Should we stream the content of the files ? + this.streamFiles = streamFiles; + // If `streamFiles` is false, we will need to accumulate the content of the + // files to calculate sizes / crc32 (and write them *before* the content). + // This boolean indicates if we are accumulating chunks (it will change a lot + // during the lifetime of this worker). + this.accumulate = false; + // The buffer receiving chunks when accumulating content. + this.contentBuffer = []; + // The list of generated directory records. + this.dirRecords = []; + // The offset (in bytes) from the beginning of the zip file for the current source. + this.currentSourceOffset = 0; + // The total number of entries in this zip file. + this.entriesCount = 0; + // the name of the file currently being added, null when handling the end of the zip file. + // Used for the emited metadata. + this.currentFile = null; + + + + this._sources = []; +} +utils.inherits(ZipFileWorker, GenericWorker); + +/** + * @see GenericWorker.push + */ +ZipFileWorker.prototype.push = function (chunk) { + + var currentFilePercent = chunk.meta.percent || 0; + var entriesCount = this.entriesCount; + var remainingFiles = this._sources.length; + + if(this.accumulate) { + this.contentBuffer.push(chunk); + } else { + this.bytesWritten += chunk.data.length; + + GenericWorker.prototype.push.call(this, { + data : chunk.data, + meta : { + currentFile : this.currentFile, + percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100 + } + }); + } +}; + +/** + * The worker started a new source (an other worker). + * @param {Object} streamInfo the streamInfo object from the new source. + */ +ZipFileWorker.prototype.openedSource = function (streamInfo) { + this.currentSourceOffset = this.bytesWritten; + this.currentFile = streamInfo['file'].name; + + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + + // don't stream folders (because they don't have any content) + if(streamedContent) { + var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + } else { + // we need to wait for the whole file before pushing anything + this.accumulate = true; + } +}; + +/** + * The worker finished a source (an other worker). + * @param {Object} streamInfo the streamInfo object from the finished source. + */ +ZipFileWorker.prototype.closedSource = function (streamInfo) { + this.accumulate = false; + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + + this.dirRecords.push(record.dirRecord); + if(streamedContent) { + // after the streamed file, we put data descriptors + this.push({ + data : generateDataDescriptors(streamInfo), + meta : {percent:100} + }); + } else { + // the content wasn't streamed, we need to push everything now + // first the file record, then the content + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + while(this.contentBuffer.length) { + this.push(this.contentBuffer.shift()); + } + } + this.currentFile = null; +}; + +/** + * @see GenericWorker.flush + */ +ZipFileWorker.prototype.flush = function () { + + var localDirLength = this.bytesWritten; + for(var i = 0; i < this.dirRecords.length; i++) { + this.push({ + data : this.dirRecords[i], + meta : {percent:100} + }); + } + var centralDirLength = this.bytesWritten - localDirLength; + + var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName); + + this.push({ + data : dirEnd, + meta : {percent:100} + }); +}; + +/** + * Prepare the next source to be read. + */ +ZipFileWorker.prototype.prepareNextSource = function () { + this.previous = this._sources.shift(); + this.openedSource(this.previous.streamInfo); + if (this.isPaused) { + this.previous.pause(); + } else { + this.previous.resume(); + } +}; + +/** + * @see GenericWorker.registerPrevious + */ +ZipFileWorker.prototype.registerPrevious = function (previous) { + this._sources.push(previous); + var self = this; + + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.closedSource(self.previous.streamInfo); + if(self._sources.length) { + self.prepareNextSource(); + } else { + self.end(); + } + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; +}; + +/** + * @see GenericWorker.resume + */ +ZipFileWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this.previous && this._sources.length) { + this.prepareNextSource(); + return true; + } + if (!this.previous && !this._sources.length && !this.generatedError) { + this.end(); + return true; + } +}; + +/** + * @see GenericWorker.error + */ +ZipFileWorker.prototype.error = function (e) { + var sources = this._sources; + if(!GenericWorker.prototype.error.call(this, e)) { + return false; + } + for(var i = 0; i < sources.length; i++) { + try { + sources[i].error(e); + } catch(e) { + // the `error` exploded, nothing to do + } + } + return true; +}; + +/** + * @see GenericWorker.lock + */ +ZipFileWorker.prototype.lock = function () { + GenericWorker.prototype.lock.call(this); + var sources = this._sources; + for(var i = 0; i < sources.length; i++) { + sources[i].lock(); + } +}; + +module.exports = ZipFileWorker; + +},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(require,module,exports){ +'use strict'; + +var compressions = require('../compressions'); +var ZipFileWorker = require('./ZipFileWorker'); + +/** + * Find the compression to use. + * @param {String} fileCompression the compression defined at the file level, if any. + * @param {String} zipCompression the compression defined at the load() level. + * @return {Object} the compression object to use. + */ +var getCompression = function (fileCompression, zipCompression) { + + var compressionName = fileCompression || zipCompression; + var compression = compressions[compressionName]; + if (!compression) { + throw new Error(compressionName + " is not a valid compression method !"); + } + return compression; +}; + +/** + * Create a worker to generate a zip file. + * @param {JSZip} zip the JSZip instance at the right root level. + * @param {Object} options to generate the zip file. + * @param {String} comment the comment to use. + */ +exports.generateWorker = function (zip, options, comment) { + + var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName); + var entriesCount = 0; + try { + + zip.forEach(function (relativePath, file) { + entriesCount++; + var compression = getCompression(file.options.compression, options.compression); + var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; + var dir = file.dir, date = file.date; + + file._compressWorker(compression, compressionOptions) + .withStreamInfo("file", { + name : relativePath, + dir : dir, + date : date, + comment : file.comment || "", + unixPermissions : file.unixPermissions, + dosPermissions : file.dosPermissions + }) + .pipe(zipFileWorker); + }); + zipFileWorker.entriesCount = entriesCount; + } catch (e) { + zipFileWorker.error(e); + } + + return zipFileWorker; +}; + +},{"../compressions":3,"./ZipFileWorker":8}],10:[function(require,module,exports){ +'use strict'; + +/** + * Representation a of zip file in js + * @constructor + */ +function JSZip() { + // if this constructor is used without `new`, it adds `new` before itself: + if(!(this instanceof JSZip)) { + return new JSZip(); + } + + if(arguments.length) { + throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); + } + + // object containing the files : + // { + // "folder/" : {...}, + // "folder/data.txt" : {...} + // } + this.files = {}; + + this.comment = null; + + // Where we are in the hierarchy + this.root = ""; + this.clone = function() { + var newObj = new JSZip(); + for (var i in this) { + if (typeof this[i] !== "function") { + newObj[i] = this[i]; + } + } + return newObj; + }; +} +JSZip.prototype = require('./object'); +JSZip.prototype.loadAsync = require('./load'); +JSZip.support = require('./support'); +JSZip.defaults = require('./defaults'); + +// TODO find a better way to handle this version, +// a require('package.json').version doesn't work with webpack, see #327 +JSZip.version = "3.1.5"; + +JSZip.loadAsync = function (content, options) { + return new JSZip().loadAsync(content, options); +}; + +JSZip.external = require("./external"); +module.exports = JSZip; + +},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(require,module,exports){ +'use strict'; +var utils = require('./utils'); +var external = require("./external"); +var utf8 = require('./utf8'); +var utils = require('./utils'); +var ZipEntries = require('./zipEntries'); +var Crc32Probe = require('./stream/Crc32Probe'); +var nodejsUtils = require("./nodejsUtils"); + +/** + * Check the CRC32 of an entry. + * @param {ZipEntry} zipEntry the zip entry to check. + * @return {Promise} the result. + */ +function checkEntryCRC32(zipEntry) { + return new external.Promise(function (resolve, reject) { + var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe()); + worker.on("error", function (e) { + reject(e); + }) + .on("end", function () { + if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) { + reject(new Error("Corrupted zip : CRC32 mismatch")); + } else { + resolve(); + } + }) + .resume(); + }); +} + +module.exports = function(data, options) { + var zip = this; + options = utils.extend(options || {}, { + base64: false, + checkCRC32: false, + optimizedBinaryString: false, + createFolders: false, + decodeFileName: utf8.utf8decode + }); + + if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + return external.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")); + } + + return utils.prepareContent("the loaded zip file", data, true, options.optimizedBinaryString, options.base64) + .then(function(data) { + var zipEntries = new ZipEntries(options); + zipEntries.load(data); + return zipEntries; + }).then(function checkCRC32(zipEntries) { + var promises = [external.Promise.resolve(zipEntries)]; + var files = zipEntries.files; + if (options.checkCRC32) { + for (var i = 0; i < files.length; i++) { + promises.push(checkEntryCRC32(files[i])); + } + } + return external.Promise.all(promises); + }).then(function addFiles(results) { + var zipEntries = results.shift(); + var files = zipEntries.files; + for (var i = 0; i < files.length; i++) { + var input = files[i]; + zip.file(input.fileNameStr, input.decompressed, { + binary: true, + optimizedBinaryString: true, + date: input.date, + dir: input.dir, + comment : input.fileCommentStr.length ? input.fileCommentStr : null, + unixPermissions : input.unixPermissions, + dosPermissions : input.dosPermissions, + createFolders: options.createFolders + }); + } + if (zipEntries.zipComment.length) { + zip.comment = zipEntries.zipComment; + } + + return zip; + }); +}; + +},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(require,module,exports){ +"use strict"; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); + +/** + * A worker that use a nodejs stream as source. + * @constructor + * @param {String} filename the name of the file entry for this stream. + * @param {Readable} stream the nodejs stream. + */ +function NodejsStreamInputAdapter(filename, stream) { + GenericWorker.call(this, "Nodejs stream input adapter for " + filename); + this._upstreamEnded = false; + this._bindStream(stream); +} + +utils.inherits(NodejsStreamInputAdapter, GenericWorker); + +/** + * Prepare the stream and bind the callbacks on it. + * Do this ASAP on node 0.10 ! A lazy binding doesn't always work. + * @param {Stream} stream the nodejs stream to use. + */ +NodejsStreamInputAdapter.prototype._bindStream = function (stream) { + var self = this; + this._stream = stream; + stream.pause(); + stream + .on("data", function (chunk) { + self.push({ + data: chunk, + meta : { + percent : 0 + } + }); + }) + .on("error", function (e) { + if(self.isPaused) { + this.generatedError = e; + } else { + self.error(e); + } + }) + .on("end", function () { + if(self.isPaused) { + self._upstreamEnded = true; + } else { + self.end(); + } + }); +}; +NodejsStreamInputAdapter.prototype.pause = function () { + if(!GenericWorker.prototype.pause.call(this)) { + return false; + } + this._stream.pause(); + return true; +}; +NodejsStreamInputAdapter.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if(this._upstreamEnded) { + this.end(); + } else { + this._stream.resume(); + } + + return true; +}; + +module.exports = NodejsStreamInputAdapter; + +},{"../stream/GenericWorker":28,"../utils":32}],13:[function(require,module,exports){ +'use strict'; + +var Readable = require('readable-stream').Readable; + +var utils = require('../utils'); +utils.inherits(NodejsStreamOutputAdapter, Readable); + +/** +* A nodejs stream using a worker as source. +* @see the SourceWrapper in http://nodejs.org/api/stream.html +* @constructor +* @param {StreamHelper} helper the helper wrapping the worker +* @param {Object} options the nodejs stream options +* @param {Function} updateCb the update callback. +*/ +function NodejsStreamOutputAdapter(helper, options, updateCb) { + Readable.call(this, options); + this._helper = helper; + + var self = this; + helper.on("data", function (data, meta) { + if (!self.push(data)) { + self._helper.pause(); + } + if(updateCb) { + updateCb(meta); + } + }) + .on("error", function(e) { + self.emit('error', e); + }) + .on("end", function () { + self.push(null); + }); +} + + +NodejsStreamOutputAdapter.prototype._read = function() { + this._helper.resume(); +}; + +module.exports = NodejsStreamOutputAdapter; + +},{"../utils":32,"readable-stream":16}],14:[function(require,module,exports){ +'use strict'; + +module.exports = { + /** + * True if this is running in Nodejs, will be undefined in a browser. + * In a browser, browserify won't include this file and the whole module + * will be resolved an empty object. + */ + isNode : typeof Buffer !== "undefined", + /** + * Create a new nodejs Buffer from an existing content. + * @param {Object} data the data to pass to the constructor. + * @param {String} encoding the encoding to use. + * @return {Buffer} a new Buffer. + */ + newBufferFrom: function(data, encoding) { + // XXX We can't use `Buffer.from` which comes from `Uint8Array.from` + // in nodejs v4 (< v.4.5). It's not the expected implementation (and + // has a different signature). + // see https://github.com/nodejs/node/issues/8053 + // A condition on nodejs' version won't solve the issue as we don't + // control the Buffer polyfills that may or may not be used. + return new Buffer(data, encoding); + }, + /** + * Create a new nodejs Buffer with the specified size. + * @param {Integer} size the size of the buffer. + * @return {Buffer} a new Buffer. + */ + allocBuffer: function (size) { + if (Buffer.alloc) { + return Buffer.alloc(size); + } else { + return new Buffer(size); + } + }, + /** + * Find out if an object is a Buffer. + * @param {Object} b the object to test. + * @return {Boolean} true if the object is a Buffer, false otherwise. + */ + isBuffer : function(b){ + return Buffer.isBuffer(b); + }, + + isStream : function (obj) { + return obj && + typeof obj.on === "function" && + typeof obj.pause === "function" && + typeof obj.resume === "function"; + } +}; + +},{}],15:[function(require,module,exports){ +'use strict'; +var utf8 = require('./utf8'); +var utils = require('./utils'); +var GenericWorker = require('./stream/GenericWorker'); +var StreamHelper = require('./stream/StreamHelper'); +var defaults = require('./defaults'); +var CompressedObject = require('./compressedObject'); +var ZipObject = require('./zipObject'); +var generate = require("./generate"); +var nodejsUtils = require("./nodejsUtils"); +var NodejsStreamInputAdapter = require("./nodejs/NodejsStreamInputAdapter"); + + +/** + * Add a file in the current folder. + * @private + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file + * @param {Object} originalOptions the options of the file + * @return {Object} the new file. + */ +var fileAdd = function(name, data, originalOptions) { + // be sure sub folders exist + var dataType = utils.getTypeOf(data), + parent; + + + /* + * Correct options. + */ + + var o = utils.extend(originalOptions || {}, defaults); + o.date = o.date || new Date(); + if (o.compression !== null) { + o.compression = o.compression.toUpperCase(); + } + + if (typeof o.unixPermissions === "string") { + o.unixPermissions = parseInt(o.unixPermissions, 8); + } + + // UNX_IFDIR 0040000 see zipinfo.c + if (o.unixPermissions && (o.unixPermissions & 0x4000)) { + o.dir = true; + } + // Bit 4 Directory + if (o.dosPermissions && (o.dosPermissions & 0x0010)) { + o.dir = true; + } + + if (o.dir) { + name = forceTrailingSlash(name); + } + if (o.createFolders && (parent = parentFolder(name))) { + folderAdd.call(this, parent, true); + } + + var isUnicodeString = dataType === "string" && o.binary === false && o.base64 === false; + if (!originalOptions || typeof originalOptions.binary === "undefined") { + o.binary = !isUnicodeString; + } + + + var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0; + + if (isCompressedEmpty || o.dir || !data || data.length === 0) { + o.base64 = false; + o.binary = true; + data = ""; + o.compression = "STORE"; + dataType = "string"; + } + + /* + * Convert content to fit. + */ + + var zipObjectContent = null; + if (data instanceof CompressedObject || data instanceof GenericWorker) { + zipObjectContent = data; + } else if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + zipObjectContent = new NodejsStreamInputAdapter(name, data); + } else { + zipObjectContent = utils.prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64); + } + + var object = new ZipObject(name, zipObjectContent, o); + this.files[name] = object; + /* + TODO: we can't throw an exception because we have async promises + (we can have a promise of a Date() for example) but returning a + promise is useless because file(name, data) returns the JSZip + object for chaining. Should we break that to allow the user + to catch the error ? + + return external.Promise.resolve(zipObjectContent) + .then(function () { + return object; + }); + */ +}; + +/** + * Find the parent folder of the path. + * @private + * @param {string} path the path to use + * @return {string} the parent folder, or "" + */ +var parentFolder = function (path) { + if (path.slice(-1) === '/') { + path = path.substring(0, path.length - 1); + } + var lastSlash = path.lastIndexOf('/'); + return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; +}; + +/** + * Returns the path with a slash at the end. + * @private + * @param {String} path the path to check. + * @return {String} the path with a trailing slash. + */ +var forceTrailingSlash = function(path) { + // Check the name ends with a / + if (path.slice(-1) !== "/") { + path += "/"; // IE doesn't like substr(-1) + } + return path; +}; + +/** + * Add a (sub) folder in the current folder. + * @private + * @param {string} name the folder's name + * @param {boolean=} [createFolders] If true, automatically create sub + * folders. Defaults to false. + * @return {Object} the new folder. + */ +var folderAdd = function(name, createFolders) { + createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders; + + name = forceTrailingSlash(name); + + // Does this folder already exist? + if (!this.files[name]) { + fileAdd.call(this, name, null, { + dir: true, + createFolders: createFolders + }); + } + return this.files[name]; +}; + +/** +* Cross-window, cross-Node-context regular expression detection +* @param {Object} object Anything +* @return {Boolean} true if the object is a regular expression, +* false otherwise +*/ +function isRegExp(object) { + return Object.prototype.toString.call(object) === "[object RegExp]"; +} + +// return the actual prototype of JSZip +var out = { + /** + * @see loadAsync + */ + load: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + + /** + * Call a callback function for each entry at this folder level. + * @param {Function} cb the callback function: + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + */ + forEach: function(cb) { + var filename, relativePath, file; + for (filename in this.files) { + if (!this.files.hasOwnProperty(filename)) { + continue; + } + file = this.files[filename]; + relativePath = filename.slice(this.root.length, filename.length); + if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root + cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn... + } + } + }, + + /** + * Filter nested files/folders with the specified function. + * @param {Function} search the predicate to use : + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + * @return {Array} An array of matching elements. + */ + filter: function(search) { + var result = []; + this.forEach(function (relativePath, entry) { + if (search(relativePath, entry)) { // the file matches the function + result.push(entry); + } + + }); + return result; + }, + + /** + * Add a file to the zip file, or search a file. + * @param {string|RegExp} name The name of the file to add (if data is defined), + * the name of the file to find (if no data) or a regex to match files. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded + * @param {Object} o File options + * @return {JSZip|Object|Array} this JSZip object (when adding a file), + * a file (when searching by string) or an array of files (when searching by regex). + */ + file: function(name, data, o) { + if (arguments.length === 1) { + if (isRegExp(name)) { + var regexp = name; + return this.filter(function(relativePath, file) { + return !file.dir && regexp.test(relativePath); + }); + } + else { // text + var obj = this.files[this.root + name]; + if (obj && !obj.dir) { + return obj; + } else { + return null; + } + } + } + else { // more than one argument : we have data ! + name = this.root + name; + fileAdd.call(this, name, data, o); + } + return this; + }, + + /** + * Add a directory to the zip file, or search. + * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. + * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. + */ + folder: function(arg) { + if (!arg) { + return this; + } + + if (isRegExp(arg)) { + return this.filter(function(relativePath, file) { + return file.dir && arg.test(relativePath); + }); + } + + // else, name is a new folder + var name = this.root + arg; + var newFolder = folderAdd.call(this, name); + + // Allow chaining by returning a new object with this folder as the root + var ret = this.clone(); + ret.root = newFolder.name; + return ret; + }, + + /** + * Delete a file, or a directory and all sub-files, from the zip + * @param {string} name the name of the file to delete + * @return {JSZip} this JSZip object + */ + remove: function(name) { + name = this.root + name; + var file = this.files[name]; + if (!file) { + // Look for any folders + if (name.slice(-1) !== "/") { + name += "/"; + } + file = this.files[name]; + } + + if (file && !file.dir) { + // file + delete this.files[name]; + } else { + // maybe a folder, delete recursively + var kids = this.filter(function(relativePath, file) { + return file.name.slice(0, name.length) === name; + }); + for (var i = 0; i < kids.length; i++) { + delete this.files[kids[i].name]; + } + } + + return this; + }, + + /** + * Generate the complete zip file + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file + */ + generate: function(options) { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + /** + * Generate the complete zip file as an internal stream. + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {StreamHelper} the streamed zip file. + */ + generateInternalStream: function(options) { + var worker, opts = {}; + try { + opts = utils.extend(options || {}, { + streamFiles: false, + compression: "STORE", + compressionOptions : null, + type: "", + platform: "DOS", + comment: null, + mimeType: 'application/zip', + encodeFileName: utf8.utf8encode + }); + + opts.type = opts.type.toLowerCase(); + opts.compression = opts.compression.toUpperCase(); + + // "binarystring" is prefered but the internals use "string". + if(opts.type === "binarystring") { + opts.type = "string"; + } + + if (!opts.type) { + throw new Error("No output type specified."); + } + + utils.checkSupport(opts.type); + + // accept nodejs `process.platform` + if( + opts.platform === 'darwin' || + opts.platform === 'freebsd' || + opts.platform === 'linux' || + opts.platform === 'sunos' + ) { + opts.platform = "UNIX"; + } + if (opts.platform === 'win32') { + opts.platform = "DOS"; + } + + var comment = opts.comment || this.comment || ""; + worker = generate.generateWorker(this, opts, comment); + } catch (e) { + worker = new GenericWorker("error"); + worker.error(e); + } + return new StreamHelper(worker, opts.type || "string", opts.mimeType); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateAsync: function(options, onUpdate) { + return this.generateInternalStream(options).accumulate(onUpdate); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateNodeStream: function(options, onUpdate) { + options = options || {}; + if (!options.type) { + options.type = "nodebuffer"; + } + return this.generateInternalStream(options).toNodejsStream(onUpdate); + } +}; +module.exports = out; + +},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(require,module,exports){ +/* + * This file is used by module bundlers (browserify/webpack/etc) when + * including a stream implementation. We use "readable-stream" to get a + * consistent behavior between nodejs versions but bundlers often have a shim + * for "stream". Using this shim greatly improve the compatibility and greatly + * reduce the final size of the bundle (only one stream implementation, not + * two). + */ +module.exports = require("stream"); + +},{"stream":undefined}],17:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function ArrayReader(data) { + DataReader.call(this, data); + for(var i = 0; i < this.data.length; i++) { + data[i] = data[i] & 0xFF; + } +} +utils.inherits(ArrayReader, DataReader); +/** + * @see DataReader.byteAt + */ +ArrayReader.prototype.byteAt = function(i) { + return this.data[this.zero + i]; +}; +/** + * @see DataReader.lastIndexOfSignature + */ +ArrayReader.prototype.lastIndexOfSignature = function(sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3); + for (var i = this.length - 4; i >= 0; --i) { + if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { + return i - this.zero; + } + } + + return -1; +}; +/** + * @see DataReader.readAndCheckSignature + */ +ArrayReader.prototype.readAndCheckSignature = function (sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3), + data = this.readData(4); + return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3]; +}; +/** + * @see DataReader.readData + */ +ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + return []; + } + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = ArrayReader; + +},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){ +'use strict'; +var utils = require('../utils'); + +function DataReader(data) { + this.data = data; // type : see implementation + this.length = data.length; + this.index = 0; + this.zero = 0; +} +DataReader.prototype = { + /** + * Check that the offset will not go too far. + * @param {string} offset the additional offset to check. + * @throws {Error} an Error if the offset is out of bounds. + */ + checkOffset: function(offset) { + this.checkIndex(this.index + offset); + }, + /** + * Check that the specified index will not be too far. + * @param {string} newIndex the index to check. + * @throws {Error} an Error if the index is out of bounds. + */ + checkIndex: function(newIndex) { + if (this.length < this.zero + newIndex || newIndex < 0) { + throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); + } + }, + /** + * Change the index. + * @param {number} newIndex The new index. + * @throws {Error} if the new index is out of the data. + */ + setIndex: function(newIndex) { + this.checkIndex(newIndex); + this.index = newIndex; + }, + /** + * Skip the next n bytes. + * @param {number} n the number of bytes to skip. + * @throws {Error} if the new index is out of the data. + */ + skip: function(n) { + this.setIndex(this.index + n); + }, + /** + * Get the byte at the specified index. + * @param {number} i the index to use. + * @return {number} a byte. + */ + byteAt: function(i) { + // see implementations + }, + /** + * Get the next number with a given byte size. + * @param {number} size the number of bytes to read. + * @return {number} the corresponding number. + */ + readInt: function(size) { + var result = 0, + i; + this.checkOffset(size); + for (i = this.index + size - 1; i >= this.index; i--) { + result = (result << 8) + this.byteAt(i); + } + this.index += size; + return result; + }, + /** + * Get the next string with a given byte size. + * @param {number} size the number of bytes to read. + * @return {string} the corresponding string. + */ + readString: function(size) { + return utils.transformTo("string", this.readData(size)); + }, + /** + * Get raw data without conversion, bytes. + * @param {number} size the number of bytes to read. + * @return {Object} the raw data, implementation specific. + */ + readData: function(size) { + // see implementations + }, + /** + * Find the last occurence of a zip signature (4 bytes). + * @param {string} sig the signature to find. + * @return {number} the index of the last occurence, -1 if not found. + */ + lastIndexOfSignature: function(sig) { + // see implementations + }, + /** + * Read the signature (4 bytes) at the current position and compare it with sig. + * @param {string} sig the expected signature + * @return {boolean} true if the signature matches, false otherwise. + */ + readAndCheckSignature: function(sig) { + // see implementations + }, + /** + * Get the next date. + * @return {Date} the date. + */ + readDate: function() { + var dostime = this.readInt(4); + return new Date(Date.UTC( + ((dostime >> 25) & 0x7f) + 1980, // year + ((dostime >> 21) & 0x0f) - 1, // month + (dostime >> 16) & 0x1f, // day + (dostime >> 11) & 0x1f, // hour + (dostime >> 5) & 0x3f, // minute + (dostime & 0x1f) << 1)); // second + } +}; +module.exports = DataReader; + +},{"../utils":32}],19:[function(require,module,exports){ +'use strict'; +var Uint8ArrayReader = require('./Uint8ArrayReader'); +var utils = require('../utils'); + +function NodeBufferReader(data) { + Uint8ArrayReader.call(this, data); +} +utils.inherits(NodeBufferReader, Uint8ArrayReader); + +/** + * @see DataReader.readData + */ +NodeBufferReader.prototype.readData = function(size) { + this.checkOffset(size); + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = NodeBufferReader; + +},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function StringReader(data) { + DataReader.call(this, data); +} +utils.inherits(StringReader, DataReader); +/** + * @see DataReader.byteAt + */ +StringReader.prototype.byteAt = function(i) { + return this.data.charCodeAt(this.zero + i); +}; +/** + * @see DataReader.lastIndexOfSignature + */ +StringReader.prototype.lastIndexOfSignature = function(sig) { + return this.data.lastIndexOf(sig) - this.zero; +}; +/** + * @see DataReader.readAndCheckSignature + */ +StringReader.prototype.readAndCheckSignature = function (sig) { + var data = this.readData(4); + return sig === data; +}; +/** + * @see DataReader.readData + */ +StringReader.prototype.readData = function(size) { + this.checkOffset(size); + // this will work because the constructor applied the "& 0xff" mask. + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = StringReader; + +},{"../utils":32,"./DataReader":18}],21:[function(require,module,exports){ +'use strict'; +var ArrayReader = require('./ArrayReader'); +var utils = require('../utils'); + +function Uint8ArrayReader(data) { + ArrayReader.call(this, data); +} +utils.inherits(Uint8ArrayReader, ArrayReader); +/** + * @see DataReader.readData + */ +Uint8ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. + return new Uint8Array(0); + } + var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = Uint8ArrayReader; + +},{"../utils":32,"./ArrayReader":17}],22:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var support = require('../support'); +var ArrayReader = require('./ArrayReader'); +var StringReader = require('./StringReader'); +var NodeBufferReader = require('./NodeBufferReader'); +var Uint8ArrayReader = require('./Uint8ArrayReader'); + +/** + * Create a reader adapted to the data. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read. + * @return {DataReader} the data reader. + */ +module.exports = function (data) { + var type = utils.getTypeOf(data); + utils.checkSupport(type); + if (type === "string" && !support.uint8array) { + return new StringReader(data); + } + if (type === "nodebuffer") { + return new NodeBufferReader(data); + } + if (support.uint8array) { + return new Uint8ArrayReader(utils.transformTo("uint8array", data)); + } + return new ArrayReader(utils.transformTo("array", data)); +}; + +},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(require,module,exports){ +'use strict'; +exports.LOCAL_FILE_HEADER = "PK\x03\x04"; +exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; +exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; +exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; +exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; +exports.DATA_DESCRIPTOR = "PK\x07\x08"; + +},{}],24:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var utils = require('../utils'); + +/** + * A worker which convert chunks to a specified type. + * @constructor + * @param {String} destType the destination type. + */ +function ConvertWorker(destType) { + GenericWorker.call(this, "ConvertWorker to " + destType); + this.destType = destType; +} +utils.inherits(ConvertWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +ConvertWorker.prototype.processChunk = function (chunk) { + this.push({ + data : utils.transformTo(this.destType, chunk.data), + meta : chunk.meta + }); +}; +module.exports = ConvertWorker; + +},{"../utils":32,"./GenericWorker":28}],25:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var crc32 = require('../crc32'); +var utils = require('../utils'); + +/** + * A worker which calculate the crc32 of the data flowing through. + * @constructor + */ +function Crc32Probe() { + GenericWorker.call(this, "Crc32Probe"); + this.withStreamInfo("crc32", 0); +} +utils.inherits(Crc32Probe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Crc32Probe.prototype.processChunk = function (chunk) { + this.streamInfo.crc32 = crc32(chunk.data, this.streamInfo.crc32 || 0); + this.push(chunk); +}; +module.exports = Crc32Probe; + +},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +/** + * A worker which calculate the total length of the data flowing through. + * @constructor + * @param {String} propName the name used to expose the length + */ +function DataLengthProbe(propName) { + GenericWorker.call(this, "DataLengthProbe for " + propName); + this.propName = propName; + this.withStreamInfo(propName, 0); +} +utils.inherits(DataLengthProbe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +DataLengthProbe.prototype.processChunk = function (chunk) { + if(chunk) { + var length = this.streamInfo[this.propName] || 0; + this.streamInfo[this.propName] = length + chunk.data.length; + } + GenericWorker.prototype.processChunk.call(this, chunk); +}; +module.exports = DataLengthProbe; + + +},{"../utils":32,"./GenericWorker":28}],27:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +// the size of the generated chunks +// TODO expose this as a public variable +var DEFAULT_BLOCK_SIZE = 16 * 1024; + +/** + * A worker that reads a content and emits chunks. + * @constructor + * @param {Promise} dataP the promise of the data to split + */ +function DataWorker(dataP) { + GenericWorker.call(this, "DataWorker"); + var self = this; + this.dataIsReady = false; + this.index = 0; + this.max = 0; + this.data = null; + this.type = ""; + + this._tickScheduled = false; + + dataP.then(function (data) { + self.dataIsReady = true; + self.data = data; + self.max = data && data.length || 0; + self.type = utils.getTypeOf(data); + if(!self.isPaused) { + self._tickAndRepeat(); + } + }, function (e) { + self.error(e); + }); +} + +utils.inherits(DataWorker, GenericWorker); + +/** + * @see GenericWorker.cleanUp + */ +DataWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this.data = null; +}; + +/** + * @see GenericWorker.resume + */ +DataWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this._tickScheduled && this.dataIsReady) { + this._tickScheduled = true; + utils.delay(this._tickAndRepeat, [], this); + } + return true; +}; + +/** + * Trigger a tick a schedule an other call to this function. + */ +DataWorker.prototype._tickAndRepeat = function() { + this._tickScheduled = false; + if(this.isPaused || this.isFinished) { + return; + } + this._tick(); + if(!this.isFinished) { + utils.delay(this._tickAndRepeat, [], this); + this._tickScheduled = true; + } +}; + +/** + * Read and push a chunk. + */ +DataWorker.prototype._tick = function() { + + if(this.isPaused || this.isFinished) { + return false; + } + + var size = DEFAULT_BLOCK_SIZE; + var data = null, nextIndex = Math.min(this.max, this.index + size); + if (this.index >= this.max) { + // EOF + return this.end(); + } else { + switch(this.type) { + case "string": + data = this.data.substring(this.index, nextIndex); + break; + case "uint8array": + data = this.data.subarray(this.index, nextIndex); + break; + case "array": + case "nodebuffer": + data = this.data.slice(this.index, nextIndex); + break; + } + this.index = nextIndex; + return this.push({ + data : data, + meta : { + percent : this.max ? this.index / this.max * 100 : 0 + } + }); + } +}; + +module.exports = DataWorker; + +},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){ +'use strict'; + +/** + * A worker that does nothing but passing chunks to the next one. This is like + * a nodejs stream but with some differences. On the good side : + * - it works on IE 6-9 without any issue / polyfill + * - it weights less than the full dependencies bundled with browserify + * - it forwards errors (no need to declare an error handler EVERYWHERE) + * + * A chunk is an object with 2 attributes : `meta` and `data`. The former is an + * object containing anything (`percent` for example), see each worker for more + * details. The latter is the real data (String, Uint8Array, etc). + * + * @constructor + * @param {String} name the name of the stream (mainly used for debugging purposes) + */ +function GenericWorker(name) { + // the name of the worker + this.name = name || "default"; + // an object containing metadata about the workers chain + this.streamInfo = {}; + // an error which happened when the worker was paused + this.generatedError = null; + // an object containing metadata to be merged by this worker into the general metadata + this.extraStreamInfo = {}; + // true if the stream is paused (and should not do anything), false otherwise + this.isPaused = true; + // true if the stream is finished (and should not do anything), false otherwise + this.isFinished = false; + // true if the stream is locked to prevent further structure updates (pipe), false otherwise + this.isLocked = false; + // the event listeners + this._listeners = { + 'data':[], + 'end':[], + 'error':[] + }; + // the previous worker, if any + this.previous = null; +} + +GenericWorker.prototype = { + /** + * Push a chunk to the next workers. + * @param {Object} chunk the chunk to push + */ + push : function (chunk) { + this.emit("data", chunk); + }, + /** + * End the stream. + * @return {Boolean} true if this call ended the worker, false otherwise. + */ + end : function () { + if (this.isFinished) { + return false; + } + + this.flush(); + try { + this.emit("end"); + this.cleanUp(); + this.isFinished = true; + } catch (e) { + this.emit("error", e); + } + return true; + }, + /** + * End the stream with an error. + * @param {Error} e the error which caused the premature end. + * @return {Boolean} true if this call ended the worker with an error, false otherwise. + */ + error : function (e) { + if (this.isFinished) { + return false; + } + + if(this.isPaused) { + this.generatedError = e; + } else { + this.isFinished = true; + + this.emit("error", e); + + // in the workers chain exploded in the middle of the chain, + // the error event will go downward but we also need to notify + // workers upward that there has been an error. + if(this.previous) { + this.previous.error(e); + } + + this.cleanUp(); + } + return true; + }, + /** + * Add a callback on an event. + * @param {String} name the name of the event (data, end, error) + * @param {Function} listener the function to call when the event is triggered + * @return {GenericWorker} the current object for chainability + */ + on : function (name, listener) { + this._listeners[name].push(listener); + return this; + }, + /** + * Clean any references when a worker is ending. + */ + cleanUp : function () { + this.streamInfo = this.generatedError = this.extraStreamInfo = null; + this._listeners = []; + }, + /** + * Trigger an event. This will call registered callback with the provided arg. + * @param {String} name the name of the event (data, end, error) + * @param {Object} arg the argument to call the callback with. + */ + emit : function (name, arg) { + if (this._listeners[name]) { + for(var i = 0; i < this._listeners[name].length; i++) { + this._listeners[name][i].call(this, arg); + } + } + }, + /** + * Chain a worker with an other. + * @param {Worker} next the worker receiving events from the current one. + * @return {worker} the next worker for chainability + */ + pipe : function (next) { + return next.registerPrevious(this); + }, + /** + * Same as `pipe` in the other direction. + * Using an API with `pipe(next)` is very easy. + * Implementing the API with the point of view of the next one registering + * a source is easier, see the ZipFileWorker. + * @param {Worker} previous the previous worker, sending events to this one + * @return {Worker} the current worker for chainability + */ + registerPrevious : function (previous) { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + + // sharing the streamInfo... + this.streamInfo = previous.streamInfo; + // ... and adding our own bits + this.mergeStreamInfo(); + this.previous = previous; + var self = this; + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.end(); + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; + }, + /** + * Pause the stream so it doesn't send events anymore. + * @return {Boolean} true if this call paused the worker, false otherwise. + */ + pause : function () { + if(this.isPaused || this.isFinished) { + return false; + } + this.isPaused = true; + + if(this.previous) { + this.previous.pause(); + } + return true; + }, + /** + * Resume a paused stream. + * @return {Boolean} true if this call resumed the worker, false otherwise. + */ + resume : function () { + if(!this.isPaused || this.isFinished) { + return false; + } + this.isPaused = false; + + // if true, the worker tried to resume but failed + var withError = false; + if(this.generatedError) { + this.error(this.generatedError); + withError = true; + } + if(this.previous) { + this.previous.resume(); + } + + return !withError; + }, + /** + * Flush any remaining bytes as the stream is ending. + */ + flush : function () {}, + /** + * Process a chunk. This is usually the method overridden. + * @param {Object} chunk the chunk to process. + */ + processChunk : function(chunk) { + this.push(chunk); + }, + /** + * Add a key/value to be added in the workers chain streamInfo once activated. + * @param {String} key the key to use + * @param {Object} value the associated value + * @return {Worker} the current worker for chainability + */ + withStreamInfo : function (key, value) { + this.extraStreamInfo[key] = value; + this.mergeStreamInfo(); + return this; + }, + /** + * Merge this worker's streamInfo into the chain's streamInfo. + */ + mergeStreamInfo : function () { + for(var key in this.extraStreamInfo) { + if (!this.extraStreamInfo.hasOwnProperty(key)) { + continue; + } + this.streamInfo[key] = this.extraStreamInfo[key]; + } + }, + + /** + * Lock the stream to prevent further updates on the workers chain. + * After calling this method, all calls to pipe will fail. + */ + lock: function () { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + this.isLocked = true; + if (this.previous) { + this.previous.lock(); + } + }, + + /** + * + * Pretty print the workers chain. + */ + toString : function () { + var me = "Worker " + this.name; + if (this.previous) { + return this.previous + " -> " + me; + } else { + return me; + } + } +}; + +module.exports = GenericWorker; + +},{}],29:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var ConvertWorker = require('./ConvertWorker'); +var GenericWorker = require('./GenericWorker'); +var base64 = require('../base64'); +var support = require("../support"); +var external = require("../external"); + +var NodejsStreamOutputAdapter = null; +if (support.nodestream) { + try { + NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter'); + } catch(e) {} +} + +/** + * Apply the final transformation of the data. If the user wants a Blob for + * example, it's easier to work with an U8intArray and finally do the + * ArrayBuffer/Blob conversion. + * @param {String} type the name of the final type + * @param {String|Uint8Array|Buffer} content the content to transform + * @param {String} mimeType the mime type of the content, if applicable. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. + */ +function transformZipOutput(type, content, mimeType) { + switch(type) { + case "blob" : + return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); + case "base64" : + return base64.encode(content); + default : + return utils.transformTo(type, content); + } +} + +/** + * Concatenate an array of data of the given type. + * @param {String} type the type of the data in the given array. + * @param {Array} dataArray the array containing the data chunks to concatenate + * @return {String|Uint8Array|Buffer} the concatenated data + * @throws Error if the asked type is unsupported + */ +function concat (type, dataArray) { + var i, index = 0, res = null, totalLength = 0; + for(i = 0; i < dataArray.length; i++) { + totalLength += dataArray[i].length; + } + switch(type) { + case "string": + return dataArray.join(""); + case "array": + return Array.prototype.concat.apply([], dataArray); + case "uint8array": + res = new Uint8Array(totalLength); + for(i = 0; i < dataArray.length; i++) { + res.set(dataArray[i], index); + index += dataArray[i].length; + } + return res; + case "nodebuffer": + return Buffer.concat(dataArray); + default: + throw new Error("concat : unsupported type '" + type + "'"); + } +} + +/** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {StreamHelper} helper the helper to use. + * @param {Function} updateCallback a callback called on each update. Called + * with one arg : + * - the metadata linked to the update received. + * @return Promise the promise for the accumulation. + */ +function accumulate(helper, updateCallback) { + return new external.Promise(function (resolve, reject){ + var dataArray = []; + var chunkType = helper._internalType, + resultType = helper._outputType, + mimeType = helper._mimeType; + helper + .on('data', function (data, meta) { + dataArray.push(data); + if(updateCallback) { + updateCallback(meta); + } + }) + .on('error', function(err) { + dataArray = []; + reject(err); + }) + .on('end', function (){ + try { + var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); + resolve(result); + } catch (e) { + reject(e); + } + dataArray = []; + }) + .resume(); + }); +} + +/** + * An helper to easily use workers outside of JSZip. + * @constructor + * @param {Worker} worker the worker to wrap + * @param {String} outputType the type of data expected by the use + * @param {String} mimeType the mime type of the content, if applicable. + */ +function StreamHelper(worker, outputType, mimeType) { + var internalType = outputType; + switch(outputType) { + case "blob": + case "arraybuffer": + internalType = "uint8array"; + break; + case "base64": + internalType = "string"; + break; + } + + try { + // the type used internally + this._internalType = internalType; + // the type used to output results + this._outputType = outputType; + // the mime type + this._mimeType = mimeType; + utils.checkSupport(internalType); + this._worker = worker.pipe(new ConvertWorker(internalType)); + // the last workers can be rewired without issues but we need to + // prevent any updates on previous workers. + worker.lock(); + } catch(e) { + this._worker = new GenericWorker("error"); + this._worker.error(e); + } +} + +StreamHelper.prototype = { + /** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {Function} updateCb the update callback. + * @return Promise the promise for the accumulation. + */ + accumulate : function (updateCb) { + return accumulate(this, updateCb); + }, + /** + * Add a listener on an event triggered on a stream. + * @param {String} evt the name of the event + * @param {Function} fn the listener + * @return {StreamHelper} the current helper. + */ + on : function (evt, fn) { + var self = this; + + if(evt === "data") { + this._worker.on(evt, function (chunk) { + fn.call(self, chunk.data, chunk.meta); + }); + } else { + this._worker.on(evt, function () { + utils.delay(fn, arguments, self); + }); + } + return this; + }, + /** + * Resume the flow of chunks. + * @return {StreamHelper} the current helper. + */ + resume : function () { + utils.delay(this._worker.resume, [], this._worker); + return this; + }, + /** + * Pause the flow of chunks. + * @return {StreamHelper} the current helper. + */ + pause : function () { + this._worker.pause(); + return this; + }, + /** + * Return a nodejs stream for this helper. + * @param {Function} updateCb the update callback. + * @return {NodejsStreamOutputAdapter} the nodejs stream. + */ + toNodejsStream : function (updateCb) { + utils.checkSupport("nodestream"); + if (this._outputType !== "nodebuffer") { + // an object stream containing blob/arraybuffer/uint8array/string + // is strange and I don't know if it would be useful. + // I you find this comment and have a good usecase, please open a + // bug report ! + throw new Error(this._outputType + " is not supported by this method"); + } + + return new NodejsStreamOutputAdapter(this, { + objectMode : this._outputType !== "nodebuffer" + }, updateCb); + } +}; + + +module.exports = StreamHelper; + +},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(require,module,exports){ +'use strict'; + +exports.base64 = true; +exports.array = true; +exports.string = true; +exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; +exports.nodebuffer = typeof Buffer !== "undefined"; +// contains true if JSZip can read/generate Uint8Array, false otherwise. +exports.uint8array = typeof Uint8Array !== "undefined"; + +if (typeof ArrayBuffer === "undefined") { + exports.blob = false; +} +else { + var buffer = new ArrayBuffer(0); + try { + exports.blob = new Blob([buffer], { + type: "application/zip" + }).size === 0; + } + catch (e) { + try { + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + exports.blob = builder.getBlob('application/zip').size === 0; + } + catch (e) { + exports.blob = false; + } + } +} + +try { + exports.nodestream = !!require('readable-stream').Readable; +} catch(e) { + exports.nodestream = false; +} + +},{"readable-stream":16}],31:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var support = require('./support'); +var nodejsUtils = require('./nodejsUtils'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * The following functions come from pako, from pako/lib/utils/strings + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new Array(256); +for (var i=0; i<256; i++) { + _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); +} +_utf8len[254]=_utf8len[254]=1; // Invalid sequence start + +// convert string to array (typed, when possible) +var string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + if (support.uint8array) { + buf = new Uint8Array(buf_len); + } else { + buf = new Array(buf_len); + } + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +var utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +// convert array to string +var buf2string = function (buf) { + var str, i, out, c, c_len; + var len = buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + // shrinkBuf(utf16buf, out) + if (utf16buf.length !== out) { + if(utf16buf.subarray) { + utf16buf = utf16buf.subarray(0, out); + } else { + utf16buf.length = out; + } + } + + // return String.fromCharCode.apply(null, utf16buf); + return utils.applyFromCharCode(utf16buf); +}; + + +// That's all for the pako functions. + + +/** + * Transform a javascript string into an array (typed if possible) of bytes, + * UTF-8 encoded. + * @param {String} str the string to encode + * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. + */ +exports.utf8encode = function utf8encode(str) { + if (support.nodebuffer) { + return nodejsUtils.newBufferFrom(str, "utf-8"); + } + + return string2buf(str); +}; + + +/** + * Transform a bytes array (or a representation) representing an UTF-8 encoded + * string into a javascript string. + * @param {Array|Uint8Array|Buffer} buf the data de decode + * @return {String} the decoded string. + */ +exports.utf8decode = function utf8decode(buf) { + if (support.nodebuffer) { + return utils.transformTo("nodebuffer", buf).toString("utf-8"); + } + + buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); + + return buf2string(buf); +}; + +/** + * A worker to decode utf8 encoded binary chunks into string chunks. + * @constructor + */ +function Utf8DecodeWorker() { + GenericWorker.call(this, "utf-8 decode"); + // the last bytes if a chunk didn't end with a complete codepoint. + this.leftOver = null; +} +utils.inherits(Utf8DecodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8DecodeWorker.prototype.processChunk = function (chunk) { + + var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data); + + // 1st step, re-use what's left of the previous chunk + if (this.leftOver && this.leftOver.length) { + if(support.uint8array) { + var previousData = data; + data = new Uint8Array(previousData.length + this.leftOver.length); + data.set(this.leftOver, 0); + data.set(previousData, this.leftOver.length); + } else { + data = this.leftOver.concat(data); + } + this.leftOver = null; + } + + var nextBoundary = utf8border(data); + var usableData = data; + if (nextBoundary !== data.length) { + if (support.uint8array) { + usableData = data.subarray(0, nextBoundary); + this.leftOver = data.subarray(nextBoundary, data.length); + } else { + usableData = data.slice(0, nextBoundary); + this.leftOver = data.slice(nextBoundary, data.length); + } + } + + this.push({ + data : exports.utf8decode(usableData), + meta : chunk.meta + }); +}; + +/** + * @see GenericWorker.flush + */ +Utf8DecodeWorker.prototype.flush = function () { + if(this.leftOver && this.leftOver.length) { + this.push({ + data : exports.utf8decode(this.leftOver), + meta : {} + }); + this.leftOver = null; + } +}; +exports.Utf8DecodeWorker = Utf8DecodeWorker; + +/** + * A worker to endcode string chunks into utf8 encoded binary chunks. + * @constructor + */ +function Utf8EncodeWorker() { + GenericWorker.call(this, "utf-8 encode"); +} +utils.inherits(Utf8EncodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8EncodeWorker.prototype.processChunk = function (chunk) { + this.push({ + data : exports.utf8encode(chunk.data), + meta : chunk.meta + }); +}; +exports.Utf8EncodeWorker = Utf8EncodeWorker; + +},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){ +'use strict'; + +var support = require('./support'); +var base64 = require('./base64'); +var nodejsUtils = require('./nodejsUtils'); +var setImmediate = require('core-js/library/fn/set-immediate'); +var external = require("./external"); + + +/** + * Convert a string that pass as a "binary string": it should represent a byte + * array but may have > 255 char codes. Be sure to take only the first byte + * and returns the byte array. + * @param {String} str the string to transform. + * @return {Array|Uint8Array} the string in a binary format. + */ +function string2binary(str) { + var result = null; + if (support.uint8array) { + result = new Uint8Array(str.length); + } else { + result = new Array(str.length); + } + return stringToArrayLike(str, result); +} + +/** + * Create a new blob with the given content and the given type. + * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use + * an Uint8Array because the stock browser of android 4 won't accept it (it + * will be silently converted to a string, "[object Uint8Array]"). + * + * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: + * when a large amount of Array is used to create the Blob, the amount of + * memory consumed is nearly 100 times the original data amount. + * + * @param {String} type the mime type of the blob. + * @return {Blob} the created blob. + */ +exports.newBlob = function(part, type) { + exports.checkSupport("blob"); + + try { + // Blob constructor + return new Blob([part], { + type: type + }); + } + catch (e) { + + try { + // deprecated, browser only, old way + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(part); + return builder.getBlob(type); + } + catch (e) { + + // well, fuck ?! + throw new Error("Bug : can't construct the Blob."); + } + } + + +}; +/** + * The identity function. + * @param {Object} input the input. + * @return {Object} the same input. + */ +function identity(input) { + return input; +} + +/** + * Fill in an array with a string. + * @param {String} str the string to use. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. + */ +function stringToArrayLike(str, array) { + for (var i = 0; i < str.length; ++i) { + array[i] = str.charCodeAt(i) & 0xFF; + } + return array; +} + +/** + * An helper for the function arrayLikeToString. + * This contains static informations and functions that + * can be optimized by the browser JIT compiler. + */ +var arrayToStringHelper = { + /** + * Transform an array of int into a string, chunk by chunk. + * See the performances notes on arrayLikeToString. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @param {String} type the type of the array. + * @param {Integer} chunk the chunk size. + * @return {String} the resulting string. + * @throws Error if the chunk is too big for the stack. + */ + stringifyByChunk: function(array, type, chunk) { + var result = [], k = 0, len = array.length; + // shortcut + if (len <= chunk) { + return String.fromCharCode.apply(null, array); + } + while (k < len) { + if (type === "array" || type === "nodebuffer") { + result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); + } + else { + result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); + } + k += chunk; + } + return result.join(""); + }, + /** + * Call String.fromCharCode on every item in the array. + * This is the naive implementation, which generate A LOT of intermediate string. + * This should be used when everything else fail. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ + stringifyByChar: function(array){ + var resultStr = ""; + for(var i = 0; i < array.length; i++) { + resultStr += String.fromCharCode(array[i]); + } + return resultStr; + }, + applyCanBeUsed : { + /** + * true if the browser accepts to use String.fromCharCode on Uint8Array + */ + uint8array : (function () { + try { + return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; + } catch (e) { + return false; + } + })(), + /** + * true if the browser accepts to use String.fromCharCode on nodejs Buffer. + */ + nodebuffer : (function () { + try { + return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; + } catch (e) { + return false; + } + })() + } +}; + +/** + * Transform an array-like object to a string. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ +function arrayLikeToString(array) { + // Performances notes : + // -------------------- + // String.fromCharCode.apply(null, array) is the fastest, see + // see http://jsperf.com/converting-a-uint8array-to-a-string/2 + // but the stack is limited (and we can get huge arrays !). + // + // result += String.fromCharCode(array[i]); generate too many strings ! + // + // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 + // TODO : we now have workers that split the work. Do we still need that ? + var chunk = 65536, + type = exports.getTypeOf(array), + canUseApply = true; + if (type === "uint8array") { + canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; + } else if (type === "nodebuffer") { + canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; + } + + if (canUseApply) { + while (chunk > 1) { + try { + return arrayToStringHelper.stringifyByChunk(array, type, chunk); + } catch (e) { + chunk = Math.floor(chunk / 2); + } + } + } + + // no apply or chunk error : slow and painful algorithm + // default browser on android 4.* + return arrayToStringHelper.stringifyByChar(array); +} + +exports.applyFromCharCode = arrayLikeToString; + + +/** + * Copy the data from an array-like to an other array-like. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. + */ +function arrayLikeToArrayLike(arrayFrom, arrayTo) { + for (var i = 0; i < arrayFrom.length; i++) { + arrayTo[i] = arrayFrom[i]; + } + return arrayTo; +} + +// a matrix containing functions to transform everything into everything. +var transform = {}; + +// string to ? +transform["string"] = { + "string": identity, + "array": function(input) { + return stringToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["string"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return stringToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": function(input) { + return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); + } +}; + +// array to ? +transform["array"] = { + "string": arrayLikeToString, + "array": identity, + "arraybuffer": function(input) { + return (new Uint8Array(input)).buffer; + }, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// arraybuffer to ? +transform["arraybuffer"] = { + "string": function(input) { + return arrayLikeToString(new Uint8Array(input)); + }, + "array": function(input) { + return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); + }, + "arraybuffer": identity, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(new Uint8Array(input)); + } +}; + +// uint8array to ? +transform["uint8array"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return input.buffer; + }, + "uint8array": identity, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// nodebuffer to ? +transform["nodebuffer"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["nodebuffer"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return arrayLikeToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": identity +}; + +/** + * Transform an input into any type. + * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. + * If no output type is specified, the unmodified input will be returned. + * @param {String} outputType the output type. + * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. + * @throws {Error} an Error if the browser doesn't support the requested output type. + */ +exports.transformTo = function(outputType, input) { + if (!input) { + // undefined, null, etc + // an empty string won't harm. + input = ""; + } + if (!outputType) { + return input; + } + exports.checkSupport(outputType); + var inputType = exports.getTypeOf(input); + var result = transform[inputType][outputType](input); + return result; +}; + +/** + * Return the type of the input. + * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. + * @param {Object} input the input to identify. + * @return {String} the (lowercase) type of the input. + */ +exports.getTypeOf = function(input) { + if (typeof input === "string") { + return "string"; + } + if (Object.prototype.toString.call(input) === "[object Array]") { + return "array"; + } + if (support.nodebuffer && nodejsUtils.isBuffer(input)) { + return "nodebuffer"; + } + if (support.uint8array && input instanceof Uint8Array) { + return "uint8array"; + } + if (support.arraybuffer && input instanceof ArrayBuffer) { + return "arraybuffer"; + } +}; + +/** + * Throw an exception if the type is not supported. + * @param {String} type the type to check. + * @throws {Error} an Error if the browser doesn't support the requested type. + */ +exports.checkSupport = function(type) { + var supported = support[type.toLowerCase()]; + if (!supported) { + throw new Error(type + " is not supported by this platform"); + } +}; + +exports.MAX_VALUE_16BITS = 65535; +exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 + +/** + * Prettify a string read as binary. + * @param {string} str the string to prettify. + * @return {string} a pretty string. + */ +exports.pretty = function(str) { + var res = '', + code, i; + for (i = 0; i < (str || "").length; i++) { + code = str.charCodeAt(i); + res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); + } + return res; +}; + +/** + * Defer the call of a function. + * @param {Function} callback the function to call asynchronously. + * @param {Array} args the arguments to give to the callback. + */ +exports.delay = function(callback, args, self) { + setImmediate(function () { + callback.apply(self || null, args || []); + }); +}; + +/** + * Extends a prototype with an other, without calling a constructor with + * side effects. Inspired by nodejs' `utils.inherits` + * @param {Function} ctor the constructor to augment + * @param {Function} superCtor the parent constructor to use + */ +exports.inherits = function (ctor, superCtor) { + var Obj = function() {}; + Obj.prototype = superCtor.prototype; + ctor.prototype = new Obj(); +}; + +/** + * Merge the objects passed as parameters into a new one. + * @private + * @param {...Object} var_args All objects to merge. + * @return {Object} a new object with the data of the others. + */ +exports.extend = function() { + var result = {}, i, attr; + for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers + for (attr in arguments[i]) { + if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { + result[attr] = arguments[i][attr]; + } + } + } + return result; +}; + +/** + * Transform arbitrary content into a Promise. + * @param {String} name a name for the content being processed. + * @param {Object} inputData the content to process. + * @param {Boolean} isBinary true if the content is not an unicode string + * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. + * @param {Boolean} isBase64 true if the string content is encoded with base64. + * @return {Promise} a promise in a format usable by JSZip. + */ +exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { + + // if inputData is already a promise, this flatten it. + var promise = external.Promise.resolve(inputData).then(function(data) { + + + var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); + + if (isBlob && typeof FileReader !== "undefined") { + return new external.Promise(function (resolve, reject) { + var reader = new FileReader(); + + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e.target.error); + }; + reader.readAsArrayBuffer(data); + }); + } else { + return data; + } + }); + + return promise.then(function(data) { + var dataType = exports.getTypeOf(data); + + if (!dataType) { + return external.Promise.reject( + new Error("Can't read the data of '" + name + "'. Is it " + + "in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") + ); + } + // special case : it's way easier to work with Uint8Array than with ArrayBuffer + if (dataType === "arraybuffer") { + data = exports.transformTo("uint8array", data); + } else if (dataType === "string") { + if (isBase64) { + data = base64.decode(data); + } + else if (isBinary) { + // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask + if (isOptimizedBinaryString !== true) { + // this is a string, not in a base64 format. + // Be sure that this is a correct "binary string" + data = string2binary(data); + } + } + } + return data; + }); +}; + +},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"core-js/library/fn/set-immediate":36}],33:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var sig = require('./signature'); +var ZipEntry = require('./zipEntry'); +var utf8 = require('./utf8'); +var support = require('./support'); +// class ZipEntries {{{ +/** + * All the entries in the zip file. + * @constructor + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntries(loadOptions) { + this.files = []; + this.loadOptions = loadOptions; +} +ZipEntries.prototype = { + /** + * Check that the reader is on the specified signature. + * @param {string} expectedSignature the expected signature. + * @throws {Error} if it is an other signature. + */ + checkSignature: function(expectedSignature) { + if (!this.reader.readAndCheckSignature(expectedSignature)) { + this.reader.index -= 4; + var signature = this.reader.readString(4); + throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); + } + }, + /** + * Check if the given signature is at the given index. + * @param {number} askedIndex the index to check. + * @param {string} expectedSignature the signature to expect. + * @return {boolean} true if the signature is here, false otherwise. + */ + isSignature: function(askedIndex, expectedSignature) { + var currentIndex = this.reader.index; + this.reader.setIndex(askedIndex); + var signature = this.reader.readString(4); + var result = signature === expectedSignature; + this.reader.setIndex(currentIndex); + return result; + }, + /** + * Read the end of the central directory. + */ + readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2); + this.diskWithCentralDirStart = this.reader.readInt(2); + this.centralDirRecordsOnThisDisk = this.reader.readInt(2); + this.centralDirRecords = this.reader.readInt(2); + this.centralDirSize = this.reader.readInt(4); + this.centralDirOffset = this.reader.readInt(4); + + this.zipCommentLength = this.reader.readInt(2); + // warning : the encoding depends of the system locale + // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. + // On a windows machine, this field is encoded with the localized windows code page. + var zipComment = this.reader.readData(this.zipCommentLength); + var decodeParamType = support.uint8array ? "uint8array" : "array"; + // To get consistent behavior with the generation part, we will assume that + // this is utf8 encoded unless specified otherwise. + var decodeContent = utils.transformTo(decodeParamType, zipComment); + this.zipComment = this.loadOptions.decodeFileName(decodeContent); + }, + /** + * Read the end of the Zip 64 central directory. + * Not merged with the method readEndOfCentral : + * The end of central can coexist with its Zip64 brother, + * I don't want to read the wrong number of bytes ! + */ + readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8); + this.reader.skip(4); + // this.versionMadeBy = this.reader.readString(2); + // this.versionNeeded = this.reader.readInt(2); + this.diskNumber = this.reader.readInt(4); + this.diskWithCentralDirStart = this.reader.readInt(4); + this.centralDirRecordsOnThisDisk = this.reader.readInt(8); + this.centralDirRecords = this.reader.readInt(8); + this.centralDirSize = this.reader.readInt(8); + this.centralDirOffset = this.reader.readInt(8); + + this.zip64ExtensibleData = {}; + var extraDataSize = this.zip64EndOfCentralSize - 44, + index = 0, + extraFieldId, + extraFieldLength, + extraFieldValue; + while (index < extraDataSize) { + extraFieldId = this.reader.readInt(2); + extraFieldLength = this.reader.readInt(4); + extraFieldValue = this.reader.readData(extraFieldLength); + this.zip64ExtensibleData[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Read the end of the Zip 64 central directory locator. + */ + readBlockZip64EndOfCentralLocator: function() { + this.diskWithZip64CentralDirStart = this.reader.readInt(4); + this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); + this.disksCount = this.reader.readInt(4); + if (this.disksCount > 1) { + throw new Error("Multi-volumes zip are not supported"); + } + }, + /** + * Read the local files, based on the offset read in the central part. + */ + readLocalFiles: function() { + var i, file; + for (i = 0; i < this.files.length; i++) { + file = this.files[i]; + this.reader.setIndex(file.localHeaderOffset); + this.checkSignature(sig.LOCAL_FILE_HEADER); + file.readLocalPart(this.reader); + file.handleUTF8(); + file.processAttributes(); + } + }, + /** + * Read the central directory. + */ + readCentralDir: function() { + var file; + + this.reader.setIndex(this.centralDirOffset); + while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) { + file = new ZipEntry({ + zip64: this.zip64 + }, this.loadOptions); + file.readCentralPart(this.reader); + this.files.push(file); + } + + if (this.centralDirRecords !== this.files.length) { + if (this.centralDirRecords !== 0 && this.files.length === 0) { + // We expected some records but couldn't find ANY. + // This is really suspicious, as if something went wrong. + throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); + } else { + // We found some records but not all. + // Something is wrong but we got something for the user: no error here. + // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length); + } + } + }, + /** + * Read the end of central directory. + */ + readEndOfCentral: function() { + var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); + if (offset < 0) { + // Check if the content is a truncated zip or complete garbage. + // A "LOCAL_FILE_HEADER" is not required at the beginning (auto + // extractible zip for example) but it can give a good hint. + // If an ajax request was used without responseType, we will also + // get unreadable data. + var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER); + + if (isGarbage) { + throw new Error("Can't find end of central directory : is this a zip file ? " + + "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"); + } else { + throw new Error("Corrupted zip: can't find end of central directory"); + } + + } + this.reader.setIndex(offset); + var endOfCentralDirOffset = offset; + this.checkSignature(sig.CENTRAL_DIRECTORY_END); + this.readBlockEndOfCentral(); + + + /* extract from the zip spec : + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + */ + if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { + this.zip64 = true; + + /* + Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from + the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents + all numbers as 64-bit double precision IEEE 754 floating point numbers. + So, we have 53bits for integers and bitwise operations treat everything as 32bits. + see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators + and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 + */ + + // should look for a zip64 EOCD locator + offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + if (offset < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + this.readBlockZip64EndOfCentralLocator(); + + // now the zip64 EOCD record + if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) { + // console.warn("ZIP64 end of central directory not where expected."); + this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + if (this.relativeOffsetEndOfZip64CentralDir < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); + } + } + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + this.readBlockZip64EndOfCentral(); + } + + var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize; + if (this.zip64) { + expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator + expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize; + } + + var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset; + + if (extraBytes > 0) { + // console.warn(extraBytes, "extra bytes at beginning or within zipfile"); + if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) { + // The offsets seem wrong, but we have something at the specified offset. + // So… we keep it. + } else { + // the offset is wrong, update the "zero" of the reader + // this happens if data has been prepended (crx files for example) + this.reader.zero = extraBytes; + } + } else if (extraBytes < 0) { + throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes."); + } + }, + prepareReader: function(data) { + this.reader = readerFor(data); + }, + /** + * Read a zip file and create ZipEntries. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. + */ + load: function(data) { + this.prepareReader(data); + this.readEndOfCentral(); + this.readCentralDir(); + this.readLocalFiles(); + } +}; +// }}} end of ZipEntries +module.exports = ZipEntries; + +},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var CompressedObject = require('./compressedObject'); +var crc32fn = require('./crc32'); +var utf8 = require('./utf8'); +var compressions = require('./compressions'); +var support = require('./support'); + +var MADE_BY_DOS = 0x00; +var MADE_BY_UNIX = 0x03; + +/** + * Find a compression registered in JSZip. + * @param {string} compressionMethod the method magic to find. + * @return {Object|null} the JSZip compression object, null if none found. + */ +var findCompression = function(compressionMethod) { + for (var method in compressions) { + if (!compressions.hasOwnProperty(method)) { + continue; + } + if (compressions[method].magic === compressionMethod) { + return compressions[method]; + } + } + return null; +}; + +// class ZipEntry {{{ +/** + * An entry in the zip file. + * @constructor + * @param {Object} options Options of the current file. + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntry(options, loadOptions) { + this.options = options; + this.loadOptions = loadOptions; +} +ZipEntry.prototype = { + /** + * say if the file is encrypted. + * @return {boolean} true if the file is encrypted, false otherwise. + */ + isEncrypted: function() { + // bit 1 is set + return (this.bitFlag & 0x0001) === 0x0001; + }, + /** + * say if the file has utf-8 filename/comment. + * @return {boolean} true if the filename/comment is in utf-8, false otherwise. + */ + useUTF8: function() { + // bit 11 is set + return (this.bitFlag & 0x0800) === 0x0800; + }, + /** + * Read the local part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readLocalPart: function(reader) { + var compression, localExtraFieldsLength; + + // we already know everything from the central dir ! + // If the central dir data are false, we are doomed. + // On the bright side, the local part is scary : zip64, data descriptors, both, etc. + // The less data we get here, the more reliable this should be. + // Let's skip the whole header and dash to the data ! + reader.skip(22); + // in some zip created on windows, the filename stored in the central dir contains \ instead of /. + // Strangely, the filename here is OK. + // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes + // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... + // Search "unzip mismatching "local" filename continuing with "central" filename version" on + // the internet. + // + // I think I see the logic here : the central directory is used to display + // content and the local directory is used to extract the files. Mixing / and \ + // may be used to display \ to windows users and use / when extracting the files. + // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 + this.fileNameLength = reader.readInt(2); + localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir + // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding. + this.fileName = reader.readData(this.fileNameLength); + reader.skip(localExtraFieldsLength); + + if (this.compressedSize === -1 || this.uncompressedSize === -1) { + throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)"); + } + + compression = findCompression(this.compressionMethod); + if (compression === null) { // no compression found + throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")"); + } + this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize)); + }, + + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readCentralPart: function(reader) { + this.versionMadeBy = reader.readInt(2); + reader.skip(2); + // this.versionNeeded = reader.readInt(2); + this.bitFlag = reader.readInt(2); + this.compressionMethod = reader.readString(2); + this.date = reader.readDate(); + this.crc32 = reader.readInt(4); + this.compressedSize = reader.readInt(4); + this.uncompressedSize = reader.readInt(4); + var fileNameLength = reader.readInt(2); + this.extraFieldsLength = reader.readInt(2); + this.fileCommentLength = reader.readInt(2); + this.diskNumberStart = reader.readInt(2); + this.internalFileAttributes = reader.readInt(2); + this.externalFileAttributes = reader.readInt(4); + this.localHeaderOffset = reader.readInt(4); + + if (this.isEncrypted()) { + throw new Error("Encrypted zip are not supported"); + } + + // will be read in the local part, see the comments there + reader.skip(fileNameLength); + this.readExtraFields(reader); + this.parseZIP64ExtraField(reader); + this.fileComment = reader.readData(this.fileCommentLength); + }, + + /** + * Parse the external file attributes and get the unix/dos permissions. + */ + processAttributes: function () { + this.unixPermissions = null; + this.dosPermissions = null; + var madeBy = this.versionMadeBy >> 8; + + // Check if we have the DOS directory flag set. + // We look for it in the DOS and UNIX permissions + // but some unknown platform could set it as a compatibility flag. + this.dir = this.externalFileAttributes & 0x0010 ? true : false; + + if(madeBy === MADE_BY_DOS) { + // first 6 bits (0 to 5) + this.dosPermissions = this.externalFileAttributes & 0x3F; + } + + if(madeBy === MADE_BY_UNIX) { + this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; + // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); + } + + // fail safe : if the name ends with a / it probably means a folder + if (!this.dir && this.fileNameStr.slice(-1) === '/') { + this.dir = true; + } + }, + + /** + * Parse the ZIP64 extra field and merge the info in the current ZipEntry. + * @param {DataReader} reader the reader to use. + */ + parseZIP64ExtraField: function(reader) { + + if (!this.extraFields[0x0001]) { + return; + } + + // should be something, preparing the extra reader + var extraReader = readerFor(this.extraFields[0x0001].value); + + // I really hope that these 64bits integer can fit in 32 bits integer, because js + // won't let us have more. + if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { + this.uncompressedSize = extraReader.readInt(8); + } + if (this.compressedSize === utils.MAX_VALUE_32BITS) { + this.compressedSize = extraReader.readInt(8); + } + if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { + this.localHeaderOffset = extraReader.readInt(8); + } + if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { + this.diskNumberStart = extraReader.readInt(4); + } + }, + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readExtraFields: function(reader) { + var end = reader.index + this.extraFieldsLength, + extraFieldId, + extraFieldLength, + extraFieldValue; + + if (!this.extraFields) { + this.extraFields = {}; + } + + while (reader.index < end) { + extraFieldId = reader.readInt(2); + extraFieldLength = reader.readInt(2); + extraFieldValue = reader.readData(extraFieldLength); + + this.extraFields[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Apply an UTF8 transformation if needed. + */ + handleUTF8: function() { + var decodeParamType = support.uint8array ? "uint8array" : "array"; + if (this.useUTF8()) { + this.fileNameStr = utf8.utf8decode(this.fileName); + this.fileCommentStr = utf8.utf8decode(this.fileComment); + } else { + var upath = this.findExtraFieldUnicodePath(); + if (upath !== null) { + this.fileNameStr = upath; + } else { + // ASCII text or unsupported code page + var fileNameByteArray = utils.transformTo(decodeParamType, this.fileName); + this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray); + } + + var ucomment = this.findExtraFieldUnicodeComment(); + if (ucomment !== null) { + this.fileCommentStr = ucomment; + } else { + // ASCII text or unsupported code page + var commentByteArray = utils.transformTo(decodeParamType, this.fileComment); + this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray); + } + } + }, + + /** + * Find the unicode path declared in the extra field, if any. + * @return {String} the unicode path, null otherwise. + */ + findExtraFieldUnicodePath: function() { + var upathField = this.extraFields[0x7075]; + if (upathField) { + var extraReader = readerFor(upathField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the filename changed, this field is out of date. + if (crc32fn(this.fileName) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(upathField.length - 5)); + } + return null; + }, + + /** + * Find the unicode comment declared in the extra field, if any. + * @return {String} the unicode comment, null otherwise. + */ + findExtraFieldUnicodeComment: function() { + var ucommentField = this.extraFields[0x6375]; + if (ucommentField) { + var extraReader = readerFor(ucommentField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the comment changed, this field is out of date. + if (crc32fn(this.fileComment) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(ucommentField.length - 5)); + } + return null; + } +}; +module.exports = ZipEntry; + +},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(require,module,exports){ +'use strict'; + +var StreamHelper = require('./stream/StreamHelper'); +var DataWorker = require('./stream/DataWorker'); +var utf8 = require('./utf8'); +var CompressedObject = require('./compressedObject'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * A simple object representing a file in the zip file. + * @constructor + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data + * @param {Object} options the options of the file + */ +var ZipObject = function(name, data, options) { + this.name = name; + this.dir = options.dir; + this.date = options.date; + this.comment = options.comment; + this.unixPermissions = options.unixPermissions; + this.dosPermissions = options.dosPermissions; + + this._data = data; + this._dataBinary = options.binary; + // keep only the compression + this.options = { + compression : options.compression, + compressionOptions : options.compressionOptions + }; +}; + +ZipObject.prototype = { + /** + * Create an internal stream for the content of this object. + * @param {String} type the type of each chunk. + * @return StreamHelper the stream. + */ + internalStream: function (type) { + var result = null, outputType = "string"; + try { + if (!type) { + throw new Error("No output type specified."); + } + outputType = type.toLowerCase(); + var askUnicodeString = outputType === "string" || outputType === "text"; + if (outputType === "binarystring" || outputType === "text") { + outputType = "string"; + } + result = this._decompressWorker(); + + var isUnicodeString = !this._dataBinary; + + if (isUnicodeString && !askUnicodeString) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + if (!isUnicodeString && askUnicodeString) { + result = result.pipe(new utf8.Utf8DecodeWorker()); + } + } catch (e) { + result = new GenericWorker("error"); + result.error(e); + } + + return new StreamHelper(result, outputType, ""); + }, + + /** + * Prepare the content in the asked type. + * @param {String} type the type of the result. + * @param {Function} onUpdate a function to call on each internal update. + * @return Promise the promise of the result. + */ + async: function (type, onUpdate) { + return this.internalStream(type).accumulate(onUpdate); + }, + + /** + * Prepare the content as a nodejs stream. + * @param {String} type the type of each chunk. + * @param {Function} onUpdate a function to call on each internal update. + * @return Stream the stream. + */ + nodeStream: function (type, onUpdate) { + return this.internalStream(type || "nodebuffer").toNodejsStream(onUpdate); + }, + + /** + * Return a worker for the compressed content. + * @private + * @param {Object} compression the compression object to use. + * @param {Object} compressionOptions the options to use when compressing. + * @return Worker the worker. + */ + _compressWorker: function (compression, compressionOptions) { + if ( + this._data instanceof CompressedObject && + this._data.compression.magic === compression.magic + ) { + return this._data.getCompressedWorker(); + } else { + var result = this._decompressWorker(); + if(!this._dataBinary) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + return CompressedObject.createWorkerFrom(result, compression, compressionOptions); + } + }, + /** + * Return a worker for the decompressed content. + * @private + * @return Worker the worker. + */ + _decompressWorker : function () { + if (this._data instanceof CompressedObject) { + return this._data.getContentWorker(); + } else if (this._data instanceof GenericWorker) { + return this._data; + } else { + return new DataWorker(this._data); + } + } +}; + +var removedMethods = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"]; +var removedFn = function () { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); +}; + +for(var i = 0; i < removedMethods.length; i++) { + ZipObject.prototype[removedMethods[i]] = removedFn; +} +module.exports = ZipObject; + +},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(require,module,exports){ +require('../modules/web.immediate'); +module.exports = require('../modules/_core').setImmediate; +},{"../modules/_core":40,"../modules/web.immediate":56}],37:[function(require,module,exports){ +module.exports = function(it){ + if(typeof it != 'function')throw TypeError(it + ' is not a function!'); + return it; +}; +},{}],38:[function(require,module,exports){ +var isObject = require('./_is-object'); +module.exports = function(it){ + if(!isObject(it))throw TypeError(it + ' is not an object!'); + return it; +}; +},{"./_is-object":51}],39:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = function(it){ + return toString.call(it).slice(8, -1); +}; +},{}],40:[function(require,module,exports){ +var core = module.exports = {version: '2.3.0'}; +if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef +},{}],41:[function(require,module,exports){ +// optional / simple context binding +var aFunction = require('./_a-function'); +module.exports = function(fn, that, length){ + aFunction(fn); + if(that === undefined)return fn; + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; +}; +},{"./_a-function":37}],42:[function(require,module,exports){ +// Thank's IE8 for his funny defineProperty +module.exports = !require('./_fails')(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_fails":45}],43:[function(require,module,exports){ +var isObject = require('./_is-object') + , document = require('./_global').document + // in old IE typeof document.createElement is 'object' + , is = isObject(document) && isObject(document.createElement); +module.exports = function(it){ + return is ? document.createElement(it) : {}; +}; +},{"./_global":46,"./_is-object":51}],44:[function(require,module,exports){ +var global = require('./_global') + , core = require('./_core') + , ctx = require('./_ctx') + , hide = require('./_hide') + , PROTOTYPE = 'prototype'; + +var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , IS_WRAP = type & $export.W + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] + , key, own, out; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if(own && key in exports)continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function(C){ + var F = function(a, b, c){ + if(this instanceof C){ + switch(arguments.length){ + case 0: return new C; + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if(IS_PROTO){ + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); + } + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; +},{"./_core":40,"./_ctx":41,"./_global":46,"./_hide":47}],45:[function(require,module,exports){ +module.exports = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } +}; +},{}],46:[function(require,module,exports){ +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); +if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef +},{}],47:[function(require,module,exports){ +var dP = require('./_object-dp') + , createDesc = require('./_property-desc'); +module.exports = require('./_descriptors') ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); +} : function(object, key, value){ + object[key] = value; + return object; +}; +},{"./_descriptors":42,"./_object-dp":52,"./_property-desc":53}],48:[function(require,module,exports){ +module.exports = require('./_global').document && document.documentElement; +},{"./_global":46}],49:[function(require,module,exports){ +module.exports = !require('./_descriptors') && !require('./_fails')(function(){ + return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_descriptors":42,"./_dom-create":43,"./_fails":45}],50:[function(require,module,exports){ +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function(fn, args, that){ + var un = that === undefined; + switch(args.length){ + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; +},{}],51:[function(require,module,exports){ +module.exports = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; +},{}],52:[function(require,module,exports){ +var anObject = require('./_an-object') + , IE8_DOM_DEFINE = require('./_ie8-dom-define') + , toPrimitive = require('./_to-primitive') + , dP = Object.defineProperty; + +exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){ + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if(IE8_DOM_DEFINE)try { + return dP(O, P, Attributes); + } catch(e){ /* empty */ } + if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); + if('value' in Attributes)O[P] = Attributes.value; + return O; +}; +},{"./_an-object":38,"./_descriptors":42,"./_ie8-dom-define":49,"./_to-primitive":55}],53:[function(require,module,exports){ +module.exports = function(bitmap, value){ + return { + enumerable : !(bitmap & 1), + configurable: !(bitmap & 2), + writable : !(bitmap & 4), + value : value + }; +}; +},{}],54:[function(require,module,exports){ +var ctx = require('./_ctx') + , invoke = require('./_invoke') + , html = require('./_html') + , cel = require('./_dom-create') + , global = require('./_global') + , process = global.process + , setTask = global.setImmediate + , clearTask = global.clearImmediate + , MessageChannel = global.MessageChannel + , counter = 0 + , queue = {} + , ONREADYSTATECHANGE = 'onreadystatechange' + , defer, channel, port; +var run = function(){ + var id = +this; + if(queue.hasOwnProperty(id)){ + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function(event){ + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if(!setTask || !clearTask){ + setTask = function setImmediate(fn){ + var args = [], i = 1; + while(arguments.length > i)args.push(arguments[i++]); + queue[++counter] = function(){ + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id){ + delete queue[id]; + }; + // Node.js 0.8- + if(require('./_cof')(process) == 'process'){ + defer = function(id){ + process.nextTick(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if(MessageChannel){ + channel = new MessageChannel; + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ + defer = function(id){ + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if(ONREADYSTATECHANGE in cel('script')){ + defer = function(id){ + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function(id){ + setTimeout(ctx(run, id, 1), 0); + }; + } +} +module.exports = { + set: setTask, + clear: clearTask +}; +},{"./_cof":39,"./_ctx":41,"./_dom-create":43,"./_global":46,"./_html":48,"./_invoke":50}],55:[function(require,module,exports){ +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = require('./_is-object'); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function(it, S){ + if(!isObject(it))return it; + var fn, val; + if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; + if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + throw TypeError("Can't convert object to primitive value"); +}; +},{"./_is-object":51}],56:[function(require,module,exports){ +var $export = require('./_export') + , $task = require('./_task'); +$export($export.G + $export.B, { + setImmediate: $task.set, + clearImmediate: $task.clear +}); +},{"./_export":44,"./_task":54}],57:[function(require,module,exports){ +(function (global){ +'use strict'; +var Mutation = global.MutationObserver || global.WebKitMutationObserver; + +var scheduleDrain; + +{ + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + scheduleDrain = function () { + element.data = (called = ++called % 2); + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + + // Create a + + - - +
    - -
    - - - - - - - -
    - - -
    -

    ACF (Bukkit) 0.5.0-SNAPSHOT API

    -
    -
    - - - - - - - - - - - - - - - - - - - - -
    Packages 
    PackageDescription
    co.aikar.commands 
    co.aikar.commands.bukkit.contexts 
    co.aikar.commands.contexts 
    -
    - -
    - - - - - - - -
    - - -

    Copyright © 2019. All rights reserved.

    +

    index.html

    +
    diff --git a/docs/acf-bukkit/overview-tree.html b/docs/acf-bukkit/overview-tree.html index 53e02190..8f23c6c2 100644 --- a/docs/acf-bukkit/overview-tree.html +++ b/docs/acf-bukkit/overview-tree.html @@ -1,12 +1,21 @@ - + - Class Hierarchy (ACF (Bukkit) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Hierarchy For All Packages

    Package Hierarchies: @@ -78,102 +102,109 @@
    +

    Class Hierarchy

    +
    +

    Enum Hierarchy

    +
    +
    + diff --git a/docs/acf-bukkit/package-search-index.js b/docs/acf-bukkit/package-search-index.js new file mode 100644 index 00000000..9b84d8e1 --- /dev/null +++ b/docs/acf-bukkit/package-search-index.js @@ -0,0 +1 @@ +packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"co.aikar.commands"},{"l":"co.aikar.commands.bukkit.contexts"},{"l":"co.aikar.commands.contexts"}] \ No newline at end of file diff --git a/docs/acf-bukkit/package-search-index.zip b/docs/acf-bukkit/package-search-index.zip new file mode 100644 index 00000000..d54b57e7 Binary files /dev/null and b/docs/acf-bukkit/package-search-index.zip differ diff --git a/docs/acf-bukkit/resources/glass.png b/docs/acf-bukkit/resources/glass.png new file mode 100644 index 00000000..a7f591f4 Binary files /dev/null and b/docs/acf-bukkit/resources/glass.png differ diff --git a/docs/acf-bukkit/resources/x.png b/docs/acf-bukkit/resources/x.png new file mode 100644 index 00000000..30548a75 Binary files /dev/null and b/docs/acf-bukkit/resources/x.png differ diff --git a/docs/acf-bukkit/script.js b/docs/acf-bukkit/script.js index b3463569..0eaaf535 100644 --- a/docs/acf-bukkit/script.js +++ b/docs/acf-bukkit/script.js @@ -1,9 +1,114 @@ -function show(type) -{ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var moduleSearchIndex; +var packageSearchIndex; +var typeSearchIndex; +var memberSearchIndex; +var tagSearchIndex; +function loadScripts(doc, tag) { + createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); + if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || + window.navigator.userAgent.indexOf('Edge/') > 0) { + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); + } + createElem(doc, tag, 'search.js'); + + $.get(pathtoroot + "module-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + moduleSearchIndex = JSON.parse(zip.file("module-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "package-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + packageSearchIndex = JSON.parse(zip.file("package-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "type-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + typeSearchIndex = JSON.parse(zip.file("type-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "member-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + memberSearchIndex = JSON.parse(zip.file("member-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "tag-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + tagSearchIndex = JSON.parse(zip.file("tag-search-index.json").asText()); + }); + }); + if (!moduleSearchIndex) { + createElem(doc, tag, 'module-search-index.js'); + } + if (!packageSearchIndex) { + createElem(doc, tag, 'package-search-index.js'); + } + if (!typeSearchIndex) { + createElem(doc, tag, 'type-search-index.js'); + } + if (!memberSearchIndex) { + createElem(doc, tag, 'member-search-index.js'); + } + if (!tagSearchIndex) { + createElem(doc, tag, 'tag-search-index.js'); + } + $(window).resize(function() { + $('.navPadding').css('padding-top', $('.fixedNav').css("height")); + }); +} + +function createElem(doc, tag, path) { + var script = doc.createElement(tag); + var scriptElement = doc.getElementsByTagName(tag)[0]; + script.src = pathtoroot + path; + scriptElement.parentNode.insertBefore(script, scriptElement); +} + +function show(type) { count = 0; - for (var key in methods) { + for (var key in data) { var row = document.getElementById(key); - if ((methods[key] & type) != 0) { + if ((data[key] & type) !== 0) { row.style.display = ''; row.className = (count++ % 2) ? rowColor : altColor; } @@ -13,8 +118,7 @@ function show(type) updateTabs(type); } -function updateTabs(type) -{ +function updateTabs(type) { for (var value in tabs) { var sNode = document.getElementById(tabs[value][0]); var spanNode = sNode.firstChild; @@ -28,3 +132,8 @@ function updateTabs(type) } } } + +function updateModuleFrame(pFrame, cFrame) { + top.packageFrame.location = pFrame; + top.classFrame.location = cFrame; +} diff --git a/docs/acf-bukkit/search.js b/docs/acf-bukkit/search.js new file mode 100644 index 00000000..b773531b --- /dev/null +++ b/docs/acf-bukkit/search.js @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var noResult = {l: "No results found"}; +var catModules = "Modules"; +var catPackages = "Packages"; +var catTypes = "Types"; +var catMembers = "Members"; +var catSearchTags = "SearchTags"; +var highlight = "$&"; +var camelCaseRegexp = ""; +var secondaryMatcher = ""; +function getHighlightedText(item) { + var ccMatcher = new RegExp(camelCaseRegexp); + var label = item.replace(ccMatcher, highlight); + if (label === item) { + label = item.replace(secondaryMatcher, highlight); + } + return label; +} +function getURLPrefix(ui) { + var urlPrefix=""; + if (useModuleDirectories) { + var slash = "/"; + if (ui.item.category === catModules) { + return ui.item.l + slash; + } else if (ui.item.category === catPackages && ui.item.m) { + return ui.item.m + slash; + } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { + $.each(packageSearchIndex, function(index, item) { + if (ui.item.p == item.l) { + urlPrefix = item.m + slash; + } + }); + return urlPrefix; + } else { + return urlPrefix; + } + } + return urlPrefix; +} +var watermark = 'Search'; +$(function() { + $("#search").val(''); + $("#search").prop("disabled", false); + $("#reset").prop("disabled", false); + $("#search").val(watermark).addClass('watermark'); + $("#search").blur(function() { + if ($(this).val().length == 0) { + $(this).val(watermark).addClass('watermark'); + } + }); + $("#search").on('click keydown', function() { + if ($(this).val() == watermark) { + $(this).val('').removeClass('watermark'); + } + }); + $("#reset").click(function() { + $("#search").val(''); + $("#search").focus(); + }); + $("#search").focus(); + $("#search")[0].setSelectionRange(0, 0); +}); +$.widget("custom.catcomplete", $.ui.autocomplete, { + _create: function() { + this._super(); + this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)"); + }, + _renderMenu: function(ul, items) { + var rMenu = this, + currentCategory = ""; + rMenu.menu.bindings = $(); + $.each(items, function(index, item) { + var li; + if (item.l !== noResult.l && item.category !== currentCategory) { + ul.append("
  • " + item.category + "
  • "); + currentCategory = item.category; + } + li = rMenu._renderItemData(ul, item); + if (item.category) { + li.attr("aria-label", item.category + " : " + item.l); + li.attr("class", "resultItem"); + } else { + li.attr("aria-label", item.l); + li.attr("class", "resultItem"); + } + }); + }, + _renderItem: function(ul, item) { + var label = ""; + if (item.category === catModules) { + label = getHighlightedText(item.l); + } else if (item.category === catPackages) { + label = (item.m) + ? getHighlightedText(item.m + "/" + item.l) + : getHighlightedText(item.l); + } else if (item.category === catTypes) { + label = (item.p) + ? getHighlightedText(item.p + "." + item.l) + : getHighlightedText(item.l); + } else if (item.category === catMembers) { + label = getHighlightedText(item.p + "." + (item.c + "." + item.l)); + } else if (item.category === catSearchTags) { + label = getHighlightedText(item.l); + } else { + label = item.l; + } + var li = $("
  • ").appendTo(ul); + var div = $("
    ").appendTo(li); + if (item.category === catSearchTags) { + if (item.d) { + div.html(label + " (" + item.h + ")
    " + + item.d + "
    "); + } else { + div.html(label + " (" + item.h + ")"); + } + } else { + div.html(label); + } + return li; + } +}); +$(function() { + $("#search").catcomplete({ + minLength: 1, + delay: 100, + source: function(request, response) { + var result = new Array(); + var presult = new Array(); + var tresult = new Array(); + var mresult = new Array(); + var tgresult = new Array(); + var secondaryresult = new Array(); + var displayCount = 0; + var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i"); + camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)"); + var camelCaseMatcher = new RegExp("^" + camelCaseRegexp); + secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); + + // Return the nested innermost name from the specified object + function nestedName(e) { + return e.l.substring(e.l.lastIndexOf(".") + 1); + } + + function concatResults(a1, a2) { + a1 = a1.concat(a2); + a2.length = 0; + return a1; + } + + if (moduleSearchIndex) { + var mdleCount = 0; + $.each(moduleSearchIndex, function(index, item) { + item.category = catModules; + if (exactMatcher.test(item.l)) { + result.push(item); + mdleCount++; + } else if (camelCaseMatcher.test(item.l)) { + result.push(item); + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + displayCount = mdleCount; + result = concatResults(result, secondaryresult); + } + if (packageSearchIndex) { + var pCount = 0; + var pkg = ""; + $.each(packageSearchIndex, function(index, item) { + item.category = catPackages; + pkg = (item.m) + ? (item.m + "/" + item.l) + : item.l; + if (exactMatcher.test(item.l)) { + presult.push(item); + pCount++; + } else if (camelCaseMatcher.test(pkg)) { + presult.push(item); + } else if (secondaryMatcher.test(pkg)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(presult, secondaryresult)); + displayCount = (pCount > displayCount) ? pCount : displayCount; + } + if (typeSearchIndex) { + var tCount = 0; + $.each(typeSearchIndex, function(index, item) { + item.category = catTypes; + var s = nestedName(item); + if (exactMatcher.test(s)) { + tresult.push(item); + tCount++; + } else if (camelCaseMatcher.test(s)) { + tresult.push(item); + } else if (secondaryMatcher.test(item.p + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tresult, secondaryresult)); + displayCount = (tCount > displayCount) ? tCount : displayCount; + } + if (memberSearchIndex) { + var mCount = 0; + $.each(memberSearchIndex, function(index, item) { + item.category = catMembers; + var s = nestedName(item); + if (exactMatcher.test(s)) { + mresult.push(item); + mCount++; + } else if (camelCaseMatcher.test(s)) { + mresult.push(item); + } else if (secondaryMatcher.test(item.c + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(mresult, secondaryresult)); + displayCount = (mCount > displayCount) ? mCount : displayCount; + } + if (tagSearchIndex) { + var tgCount = 0; + $.each(tagSearchIndex, function(index, item) { + item.category = catSearchTags; + if (exactMatcher.test(item.l)) { + tgresult.push(item); + tgCount++; + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tgresult, secondaryresult)); + displayCount = (tgCount > displayCount) ? tgCount : displayCount; + } + displayCount = (displayCount > 500) ? displayCount : 500; + var counter = function() { + var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0}; + var f = function(item) { + count[item.category] += 1; + return (count[item.category] <= displayCount); + }; + return f; + }(); + response(result.filter(counter)); + }, + response: function(event, ui) { + if (!ui.content.length) { + ui.content.push(noResult); + } else { + $("#search").empty(); + } + }, + autoFocus: true, + position: { + collision: "flip" + }, + select: function(event, ui) { + if (ui.item.l !== noResult.l) { + var url = getURLPrefix(ui); + if (ui.item.category === catModules) { + if (useModuleDirectories) { + url += "module-summary.html"; + } else { + url = ui.item.l + "-summary.html"; + } + } else if (ui.item.category === catPackages) { + if (ui.item.url) { + url = ui.item.url; + } else { + url += ui.item.l.replace(/\./g, '/') + "/package-summary.html"; + } + } else if (ui.item.category === catTypes) { + if (ui.item.url) { + url = ui.item.url; + } else if (ui.item.p === "") { + url += ui.item.l + ".html"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; + } + } else if (ui.item.category === catMembers) { + if (ui.item.p === "") { + url += ui.item.c + ".html" + "#"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; + } + if (ui.item.url) { + url += ui.item.url; + } else { + url += ui.item.l; + } + } else if (ui.item.category === catSearchTags) { + url += ui.item.u; + } + if (top !== window) { + parent.classFrame.location = pathtoroot + url; + } else { + window.location.href = pathtoroot + url; + } + $("#search").focus(); + } + } + }); +}); diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/ACFBukkitHelpTopic.html b/docs/acf-bukkit/src-html/co/aikar/commands/ACFBukkitHelpTopic.html index 0d9cb071..0471a414 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/ACFBukkitHelpTopic.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/ACFBukkitHelpTopic.html @@ -1,58 +1,59 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.bukkit.Bukkit;
    -027import org.bukkit.help.GenericCommandHelpTopic;
    -028
    -029import java.util.ArrayList;
    -030import java.util.List;
    -031
    -032public class ACFBukkitHelpTopic extends GenericCommandHelpTopic {
    -033
    -034    public ACFBukkitHelpTopic(BukkitCommandManager manager, BukkitRootCommand command) {
    -035        super(command);
    -036
    -037        List<String> messages = new ArrayList<>();
    -038        BukkitCommandIssuer captureIssuer = new BukkitCommandIssuer(manager, Bukkit.getConsoleSender()) {
    -039            @Override
    -040            public void sendMessageInternal(String message) {
    -041                messages.add(message);
    -042            }
    -043        };
    -044        manager.generateCommandHelp(captureIssuer, command).showHelp(captureIssuer);
    -045        this.fullText = ACFUtil.join(messages, "\n");
    -046    }
    -047}
    +
    001/*
    +002 * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.bukkit.Bukkit;
    +027import org.bukkit.help.GenericCommandHelpTopic;
    +028
    +029import java.util.ArrayList;
    +030import java.util.List;
    +031
    +032public class ACFBukkitHelpTopic extends GenericCommandHelpTopic {
    +033
    +034    public ACFBukkitHelpTopic(BukkitCommandManager manager, BukkitRootCommand command) {
    +035        super(command);
    +036
    +037        List<String> messages = new ArrayList<>();
    +038        BukkitCommandIssuer captureIssuer = new BukkitCommandIssuer(manager, Bukkit.getConsoleSender()) {
    +039            @Override
    +040            public void sendMessageInternal(String message) {
    +041                messages.add(message);
    +042            }
    +043        };
    +044        manager.generateCommandHelp(captureIssuer, command).showHelp(captureIssuer);
    +045        this.fullText = ACFUtil.join(messages, "\n");
    +046    }
    +047}
     
     
     
    @@ -115,5 +116,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/ACFBukkitUtil.html b/docs/acf-bukkit/src-html/co/aikar/commands/ACFBukkitUtil.html index 4623b039..3770a121 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/ACFBukkitUtil.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/ACFBukkitUtil.html @@ -1,342 +1,343 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.bukkit.Bukkit;
    -027import org.bukkit.ChatColor;
    -028import org.bukkit.Location;
    -029import org.bukkit.Material;
    -030import org.bukkit.World;
    -031import org.bukkit.command.CommandSender;
    -032import org.bukkit.entity.Entity;
    -033import org.bukkit.entity.Player;
    -034import org.bukkit.inventory.ItemStack;
    -035import org.jetbrains.annotations.NotNull;
    -036
    -037import java.util.ArrayList;
    -038import java.util.Iterator;
    -039import java.util.List;
    -040import java.util.Set;
    -041import java.util.regex.Pattern;
    -042import java.util.stream.Collectors;
    -043
    -044public class ACFBukkitUtil {
    -045
    -046    public static String formatLocation(Location loc) {
    -047        if (loc == null) {
    -048            return null;
    -049        }
    -050        return loc.getWorld().getName() +
    -051                ":" +
    -052                loc.getBlockX() +
    -053                "," +
    -054                loc.getBlockY() +
    -055                "," +
    -056                loc.getBlockZ();
    -057    }
    -058
    -059    public static String color(String message) {
    -060        return ChatColor.translateAlternateColorCodes('&', message);
    -061    }
    -062
    -063    /**
    -064     * Move to Message Keys on the CommandIssuer
    -065     *
    -066     * @deprecated
    -067     */
    -068    @Deprecated
    -069    public static void sendMsg(CommandSender player, String message) {
    -070        message = color(message);
    -071        for (String msg : ACFPatterns.NEWLINE.split(message)) {
    -072            player.sendMessage(msg);
    -073        }
    -074    }
    -075
    -076    public static Location stringToLocation(String storedLoc) {
    -077        return stringToLocation(storedLoc, null);
    -078    }
    -079
    -080    public static Location stringToLocation(String storedLoc, World forcedWorld) {
    -081        if (storedLoc == null) {
    -082            return null;
    -083        }
    -084        String[] args = ACFPatterns.COLON.split(storedLoc);
    -085        if (args.length >= 4 || (args.length == 3 && forcedWorld != null)) {
    -086            String world = forcedWorld != null ? forcedWorld.getName() : args[0];
    -087            int i = args.length == 3 ? 0 : 1;
    -088            double x = Double.parseDouble(args[i]);
    -089            double y = Double.parseDouble(args[i + 1]);
    -090            double z = Double.parseDouble(args[i + 2]);
    -091            Location loc = new Location(Bukkit.getWorld(world), x, y, z);
    -092            if (args.length >= 6) {
    -093                loc.setPitch(Float.parseFloat(args[4]));
    -094                loc.setYaw(Float.parseFloat(args[5]));
    -095            }
    -096            return loc;
    -097        } else if (args.length == 2) {
    -098            String[] args2 = ACFPatterns.COMMA.split(args[1]);
    -099            if (args2.length == 3) {
    -100                String world = forcedWorld != null ? forcedWorld.getName() : args[0];
    -101                double x = Double.parseDouble(args2[0]);
    -102                double y = Double.parseDouble(args2[1]);
    -103                double z = Double.parseDouble(args2[2]);
    -104                return new Location(Bukkit.getWorld(world), x, y, z);
    -105            }
    -106        }
    -107        return null;
    -108    }
    -109
    -110    public static String fullLocationToString(Location loc) {
    -111        if (loc == null) {
    -112            return null;
    -113        }
    -114        return (new StringBuilder(64))
    -115                .append(loc.getWorld().getName())
    -116                .append(':')
    -117                .append(ACFUtil.precision(loc.getX(), 4))
    -118                .append(':')
    -119                .append(ACFUtil.precision(loc.getY(), 4))
    -120                .append(':')
    -121                .append(ACFUtil.precision(loc.getZ(), 4))
    -122                .append(':')
    -123                .append(ACFUtil.precision(loc.getPitch(), 4))
    -124                .append(':')
    -125                .append(ACFUtil.precision(loc.getYaw(), 4))
    -126                .toString();
    -127    }
    -128
    -129    public static String fullBlockLocationToString(Location loc) {
    -130        if (loc == null) {
    -131            return null;
    -132        }
    -133        return (new StringBuilder(64))
    -134                .append(loc.getWorld().getName())
    -135                .append(':')
    -136                .append(loc.getBlockX())
    -137                .append(':')
    -138                .append(loc.getBlockY())
    -139                .append(':')
    -140                .append(loc.getBlockZ())
    -141                .append(':')
    -142                .append(ACFUtil.precision(loc.getPitch(), 4))
    -143                .append(':')
    -144                .append(ACFUtil.precision(loc.getYaw(), 4))
    -145                .toString();
    -146    }
    -147
    -148    public static String blockLocationToString(Location loc) {
    -149        if (loc == null) {
    -150            return null;
    -151        }
    -152
    -153        return (new StringBuilder(32))
    -154                .append(loc.getWorld().getName())
    -155                .append(':')
    -156                .append(loc.getBlockX())
    -157                .append(':')
    -158                .append(loc.getBlockY())
    -159                .append(':')
    -160                .append(loc.getBlockZ())
    -161                .toString();
    -162    }
    -163
    -164    public static double distance(@NotNull Entity e1, @NotNull Entity e2) {
    -165        return distance(e1.getLocation(), e2.getLocation());
    -166    }
    -167
    -168    public static double distance2d(@NotNull Entity e1, @NotNull Entity e2) {
    -169        return distance2d(e1.getLocation(), e2.getLocation());
    -170    }
    -171
    -172    public static double distance2d(@NotNull Location loc1, @NotNull Location loc2) {
    -173        loc1 = loc1.clone();
    -174        loc1.setY(loc2.getY());
    -175        return distance(loc1, loc2);
    -176    }
    -177
    -178    public static double distance(@NotNull Location loc1, @NotNull Location loc2) {
    -179        if (loc1.getWorld() != loc2.getWorld()) {
    -180            return 0;
    -181        }
    -182        return loc1.distance(loc2);
    -183    }
    -184
    -185    public static Location getTargetLoc(Player player) {
    -186        return getTargetLoc(player, 128);
    -187    }
    -188
    -189    public static Location getTargetLoc(Player player, int maxDist) {
    -190        return getTargetLoc(player, maxDist, 1.5);
    -191    }
    -192
    -193    public static Location getTargetLoc(Player player, int maxDist, double addY) {
    -194        try {
    -195            Location target = player.getTargetBlock((Set<Material>) null, maxDist).getLocation();
    -196            target.setY(target.getY() + addY);
    -197            return target;
    -198        } catch (Exception ignored) {
    -199            return null;
    -200        }
    -201    }
    -202
    -203    public static Location getRandLoc(Location loc, int radius) {
    -204        return getRandLoc(loc, radius, radius, radius);
    -205    }
    -206
    -207    public static Location getRandLoc(Location loc, int xzRadius, int yRadius) {
    -208        return getRandLoc(loc, xzRadius, yRadius, xzRadius);
    -209    }
    -210
    -211    @NotNull
    -212    public static Location getRandLoc(Location loc, int xRadius, int yRadius, int zRadius) {
    -213        Location newLoc = loc.clone();
    -214        newLoc.setX(ACFUtil.rand(loc.getX() - xRadius, loc.getX() + xRadius));
    -215        newLoc.setY(ACFUtil.rand(loc.getY() - yRadius, loc.getY() + yRadius));
    -216        newLoc.setZ(ACFUtil.rand(loc.getZ() - zRadius, loc.getZ() + zRadius));
    -217        return newLoc;
    -218    }
    -219
    -220
    -221    public static String removeColors(String msg) {
    -222        return ChatColor.stripColor(color(msg));
    -223    }
    -224
    -225    public static String replaceChatString(String message, String replace, String with) {
    -226        return replaceChatString(message, Pattern.compile(Pattern.quote(replace), Pattern.CASE_INSENSITIVE), with);
    -227    }
    -228
    -229    public static String replaceChatString(String message, Pattern replace, String with) {
    -230        final String[] split = replace.split(message + "1");
    -231
    -232        if (split.length < 2) {
    -233            return replace.matcher(message).replaceAll(with);
    -234        }
    -235        message = split[0];
    -236
    -237        for (int i = 1; i < split.length; i++) {
    -238            final String prev = ChatColor.getLastColors(message);
    -239            message += with + prev + split[i];
    -240        }
    -241        return message.substring(0, message.length() - 1);
    -242    }
    -243
    -244    public static boolean isWithinDistance(@NotNull Player p1, @NotNull Player p2, int dist) {
    -245        return isWithinDistance(p1.getLocation(), p2.getLocation(), dist);
    -246    }
    -247
    -248    public static boolean isWithinDistance(@NotNull Location loc1, @NotNull Location loc2, int dist) {
    -249        return loc1.getWorld() == loc2.getWorld() && loc1.distance(loc2) <= dist;
    -250    }
    -251
    -252    /**
    -253     * Please move to the CommandIssuer version
    -254     *
    -255     * @deprecated
    -256     */
    -257    public static Player findPlayerSmart(CommandSender requester, String search) {
    -258        CommandManager manager = CommandManager.getCurrentCommandManager();
    -259        if (manager != null) {
    -260            return findPlayerSmart(manager.getCommandIssuer(requester), search);
    -261        }
    -262        throw new IllegalStateException("You may not use the ACFBukkitUtil#findPlayerSmart(CommandSender) async to the command execution.");
    -263    }
    -264
    -265    public static Player findPlayerSmart(CommandIssuer issuer, String search) {
    -266        CommandSender requester = issuer.getIssuer();
    -267        if (search == null) {
    -268            return null;
    -269        }
    -270        String name = ACFUtil.replace(search, ":confirm", "");
    -271
    -272        if (!isValidName(name)) {
    -273            issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
    -274            return null;
    -275        }
    -276
    -277        List<Player> matches = Bukkit.getServer().matchPlayer(name);
    -278        List<Player> confirmList = new ArrayList<>();
    -279        findMatches(search, requester, matches, confirmList);
    -280
    -281
    -282        if (matches.size() > 1 || confirmList.size() > 1) {
    -283            String allMatches = matches.stream().map(Player::getName).collect(Collectors.joining(", "));
    -284            issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH,
    -285                    "{search}", name, "{all}", allMatches);
    -286            return null;
    -287        }
    -288
    -289        //noinspection Duplicates
    -290        if (matches.isEmpty()) {
    -291            Player player = ACFUtil.getFirstElement(confirmList);
    -292            if (player == null) {
    -293                issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name);
    -294                return null;
    -295            } else {
    -296                issuer.sendInfo(MinecraftMessageKeys.PLAYER_IS_VANISHED_CONFIRM, "{vanished}", player.getName());
    -297                return null;
    -298            }
    -299        }
    -300
    -301        return matches.get(0);
    -302    }
    -303
    -304    private static void findMatches(String search, CommandSender requester, List<Player> matches, List<Player> confirmList) {
    -305        // Remove vanished players from smart matching.
    -306        Iterator<Player> iter = matches.iterator();
    -307        //noinspection Duplicates
    -308        while (iter.hasNext()) {
    -309            Player player = iter.next();
    -310            if (requester instanceof Player && !((Player) requester).canSee(player)) {
    -311                if (requester.hasPermission("acf.seevanish")) {
    -312                    if (!search.endsWith(":confirm")) {
    -313                        confirmList.add(player);
    -314                        iter.remove();
    -315                    }
    -316                } else {
    -317                    iter.remove();
    -318                }
    -319            }
    -320        }
    -321    }
    -322
    -323
    -324    public static boolean isValidName(String name) {
    -325        return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches();
    -326    }
    -327
    -328    static boolean isValidItem(ItemStack item) {
    -329        return item != null && item.getType() != Material.AIR && item.getAmount() > 0;
    -330    }
    -331}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.bukkit.Bukkit;
    +027import org.bukkit.ChatColor;
    +028import org.bukkit.Location;
    +029import org.bukkit.Material;
    +030import org.bukkit.World;
    +031import org.bukkit.command.CommandSender;
    +032import org.bukkit.entity.Entity;
    +033import org.bukkit.entity.Player;
    +034import org.bukkit.inventory.ItemStack;
    +035import org.jetbrains.annotations.NotNull;
    +036
    +037import java.util.ArrayList;
    +038import java.util.Iterator;
    +039import java.util.List;
    +040import java.util.Set;
    +041import java.util.regex.Pattern;
    +042import java.util.stream.Collectors;
    +043
    +044public class ACFBukkitUtil {
    +045
    +046    public static String formatLocation(Location loc) {
    +047        if (loc == null) {
    +048            return null;
    +049        }
    +050        return loc.getWorld().getName() +
    +051                ":" +
    +052                loc.getBlockX() +
    +053                "," +
    +054                loc.getBlockY() +
    +055                "," +
    +056                loc.getBlockZ();
    +057    }
    +058
    +059    public static String color(String message) {
    +060        return ChatColor.translateAlternateColorCodes('&', message);
    +061    }
    +062
    +063    /**
    +064     * Move to Message Keys on the CommandIssuer
    +065     *
    +066     * @deprecated
    +067     */
    +068    @Deprecated
    +069    public static void sendMsg(CommandSender player, String message) {
    +070        message = color(message);
    +071        for (String msg : ACFPatterns.NEWLINE.split(message)) {
    +072            player.sendMessage(msg);
    +073        }
    +074    }
    +075
    +076    public static Location stringToLocation(String storedLoc) {
    +077        return stringToLocation(storedLoc, null);
    +078    }
    +079
    +080    public static Location stringToLocation(String storedLoc, World forcedWorld) {
    +081        if (storedLoc == null) {
    +082            return null;
    +083        }
    +084        String[] args = ACFPatterns.COLON.split(storedLoc);
    +085        if (args.length >= 4 || (args.length == 3 && forcedWorld != null)) {
    +086            String world = forcedWorld != null ? forcedWorld.getName() : args[0];
    +087            int i = args.length == 3 ? 0 : 1;
    +088            double x = Double.parseDouble(args[i]);
    +089            double y = Double.parseDouble(args[i + 1]);
    +090            double z = Double.parseDouble(args[i + 2]);
    +091            Location loc = new Location(Bukkit.getWorld(world), x, y, z);
    +092            if (args.length >= 6) {
    +093                loc.setPitch(Float.parseFloat(args[4]));
    +094                loc.setYaw(Float.parseFloat(args[5]));
    +095            }
    +096            return loc;
    +097        } else if (args.length == 2) {
    +098            String[] args2 = ACFPatterns.COMMA.split(args[1]);
    +099            if (args2.length == 3) {
    +100                String world = forcedWorld != null ? forcedWorld.getName() : args[0];
    +101                double x = Double.parseDouble(args2[0]);
    +102                double y = Double.parseDouble(args2[1]);
    +103                double z = Double.parseDouble(args2[2]);
    +104                return new Location(Bukkit.getWorld(world), x, y, z);
    +105            }
    +106        }
    +107        return null;
    +108    }
    +109
    +110    public static String fullLocationToString(Location loc) {
    +111        if (loc == null) {
    +112            return null;
    +113        }
    +114        return (new StringBuilder(64))
    +115                .append(loc.getWorld().getName())
    +116                .append(':')
    +117                .append(ACFUtil.precision(loc.getX(), 4))
    +118                .append(':')
    +119                .append(ACFUtil.precision(loc.getY(), 4))
    +120                .append(':')
    +121                .append(ACFUtil.precision(loc.getZ(), 4))
    +122                .append(':')
    +123                .append(ACFUtil.precision(loc.getPitch(), 4))
    +124                .append(':')
    +125                .append(ACFUtil.precision(loc.getYaw(), 4))
    +126                .toString();
    +127    }
    +128
    +129    public static String fullBlockLocationToString(Location loc) {
    +130        if (loc == null) {
    +131            return null;
    +132        }
    +133        return (new StringBuilder(64))
    +134                .append(loc.getWorld().getName())
    +135                .append(':')
    +136                .append(loc.getBlockX())
    +137                .append(':')
    +138                .append(loc.getBlockY())
    +139                .append(':')
    +140                .append(loc.getBlockZ())
    +141                .append(':')
    +142                .append(ACFUtil.precision(loc.getPitch(), 4))
    +143                .append(':')
    +144                .append(ACFUtil.precision(loc.getYaw(), 4))
    +145                .toString();
    +146    }
    +147
    +148    public static String blockLocationToString(Location loc) {
    +149        if (loc == null) {
    +150            return null;
    +151        }
    +152
    +153        return (new StringBuilder(32))
    +154                .append(loc.getWorld().getName())
    +155                .append(':')
    +156                .append(loc.getBlockX())
    +157                .append(':')
    +158                .append(loc.getBlockY())
    +159                .append(':')
    +160                .append(loc.getBlockZ())
    +161                .toString();
    +162    }
    +163
    +164    public static double distance(@NotNull Entity e1, @NotNull Entity e2) {
    +165        return distance(e1.getLocation(), e2.getLocation());
    +166    }
    +167
    +168    public static double distance2d(@NotNull Entity e1, @NotNull Entity e2) {
    +169        return distance2d(e1.getLocation(), e2.getLocation());
    +170    }
    +171
    +172    public static double distance2d(@NotNull Location loc1, @NotNull Location loc2) {
    +173        loc1 = loc1.clone();
    +174        loc1.setY(loc2.getY());
    +175        return distance(loc1, loc2);
    +176    }
    +177
    +178    public static double distance(@NotNull Location loc1, @NotNull Location loc2) {
    +179        if (loc1.getWorld() != loc2.getWorld()) {
    +180            return 0;
    +181        }
    +182        return loc1.distance(loc2);
    +183    }
    +184
    +185    public static Location getTargetLoc(Player player) {
    +186        return getTargetLoc(player, 128);
    +187    }
    +188
    +189    public static Location getTargetLoc(Player player, int maxDist) {
    +190        return getTargetLoc(player, maxDist, 1.5);
    +191    }
    +192
    +193    public static Location getTargetLoc(Player player, int maxDist, double addY) {
    +194        try {
    +195            Location target = player.getTargetBlock((Set<Material>) null, maxDist).getLocation();
    +196            target.setY(target.getY() + addY);
    +197            return target;
    +198        } catch (Exception ignored) {
    +199            return null;
    +200        }
    +201    }
    +202
    +203    public static Location getRandLoc(Location loc, int radius) {
    +204        return getRandLoc(loc, radius, radius, radius);
    +205    }
    +206
    +207    public static Location getRandLoc(Location loc, int xzRadius, int yRadius) {
    +208        return getRandLoc(loc, xzRadius, yRadius, xzRadius);
    +209    }
    +210
    +211    @NotNull
    +212    public static Location getRandLoc(Location loc, int xRadius, int yRadius, int zRadius) {
    +213        Location newLoc = loc.clone();
    +214        newLoc.setX(ACFUtil.rand(loc.getX() - xRadius, loc.getX() + xRadius));
    +215        newLoc.setY(ACFUtil.rand(loc.getY() - yRadius, loc.getY() + yRadius));
    +216        newLoc.setZ(ACFUtil.rand(loc.getZ() - zRadius, loc.getZ() + zRadius));
    +217        return newLoc;
    +218    }
    +219
    +220
    +221    public static String removeColors(String msg) {
    +222        return ChatColor.stripColor(color(msg));
    +223    }
    +224
    +225    public static String replaceChatString(String message, String replace, String with) {
    +226        return replaceChatString(message, Pattern.compile(Pattern.quote(replace), Pattern.CASE_INSENSITIVE), with);
    +227    }
    +228
    +229    public static String replaceChatString(String message, Pattern replace, String with) {
    +230        final String[] split = replace.split(message + "1");
    +231
    +232        if (split.length < 2) {
    +233            return replace.matcher(message).replaceAll(with);
    +234        }
    +235        message = split[0];
    +236
    +237        for (int i = 1; i < split.length; i++) {
    +238            final String prev = ChatColor.getLastColors(message);
    +239            message += with + prev + split[i];
    +240        }
    +241        return message.substring(0, message.length() - 1);
    +242    }
    +243
    +244    public static boolean isWithinDistance(@NotNull Player p1, @NotNull Player p2, int dist) {
    +245        return isWithinDistance(p1.getLocation(), p2.getLocation(), dist);
    +246    }
    +247
    +248    public static boolean isWithinDistance(@NotNull Location loc1, @NotNull Location loc2, int dist) {
    +249        return loc1.getWorld() == loc2.getWorld() && loc1.distance(loc2) <= dist;
    +250    }
    +251
    +252    /**
    +253     * Please move to the CommandIssuer version
    +254     *
    +255     * @deprecated
    +256     */
    +257    public static Player findPlayerSmart(CommandSender requester, String search) {
    +258        CommandManager manager = CommandManager.getCurrentCommandManager();
    +259        if (manager != null) {
    +260            return findPlayerSmart(manager.getCommandIssuer(requester), search);
    +261        }
    +262        throw new IllegalStateException("You may not use the ACFBukkitUtil#findPlayerSmart(CommandSender) async to the command execution.");
    +263    }
    +264
    +265    public static Player findPlayerSmart(CommandIssuer issuer, String search) {
    +266        CommandSender requester = issuer.getIssuer();
    +267        if (search == null) {
    +268            return null;
    +269        }
    +270        String name = ACFUtil.replace(search, ":confirm", "");
    +271
    +272        if (!isValidName(name)) {
    +273            issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
    +274            return null;
    +275        }
    +276
    +277        List<Player> matches = Bukkit.getServer().matchPlayer(name);
    +278        List<Player> confirmList = new ArrayList<>();
    +279        findMatches(search, requester, matches, confirmList);
    +280
    +281
    +282        if (matches.size() > 1 || confirmList.size() > 1) {
    +283            String allMatches = matches.stream().map(Player::getName).collect(Collectors.joining(", "));
    +284            issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH,
    +285                    "{search}", name, "{all}", allMatches);
    +286            return null;
    +287        }
    +288
    +289        //noinspection Duplicates
    +290        if (matches.isEmpty()) {
    +291            Player player = ACFUtil.getFirstElement(confirmList);
    +292            if (player == null) {
    +293                issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name);
    +294                return null;
    +295            } else {
    +296                issuer.sendInfo(MinecraftMessageKeys.PLAYER_IS_VANISHED_CONFIRM, "{vanished}", player.getName());
    +297                return null;
    +298            }
    +299        }
    +300
    +301        return matches.get(0);
    +302    }
    +303
    +304    private static void findMatches(String search, CommandSender requester, List<Player> matches, List<Player> confirmList) {
    +305        // Remove vanished players from smart matching.
    +306        Iterator<Player> iter = matches.iterator();
    +307        //noinspection Duplicates
    +308        while (iter.hasNext()) {
    +309            Player player = iter.next();
    +310            if (requester instanceof Player && !((Player) requester).canSee(player)) {
    +311                if (requester.hasPermission("acf.seevanish")) {
    +312                    if (!search.endsWith(":confirm")) {
    +313                        confirmList.add(player);
    +314                        iter.remove();
    +315                    }
    +316                } else {
    +317                    iter.remove();
    +318                }
    +319            }
    +320        }
    +321    }
    +322
    +323
    +324    public static boolean isValidName(String name) {
    +325        return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches();
    +326    }
    +327
    +328    static boolean isValidItem(ItemStack item) {
    +329        return item != null && item.getType() != Material.AIR && item.getAmount() > 0;
    +330    }
    +331}
     
     
     
    @@ -399,5 +400,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandCompletionContext.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandCompletionContext.html index 0da26eaa..cef70236 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandCompletionContext.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandCompletionContext.html @@ -1,56 +1,57 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.bukkit.command.CommandSender;
    -027import org.bukkit.entity.Player;
    -028
    -029public class BukkitCommandCompletionContext extends CommandCompletionContext<BukkitCommandIssuer> {
    -030    BukkitCommandCompletionContext(RegisteredCommand command, BukkitCommandIssuer issuer, String input, String config, String[] args) {
    -031        super(command, issuer, input, config, args);
    -032    }
    -033
    -034    public CommandSender getSender() {
    -035        return this.getIssuer().getIssuer();
    -036    }
    -037
    -038    /**
    -039     * Returns the Player object if this Issuer is a Player
    -040     * @return
    -041     */
    -042    public Player getPlayer() {
    -043        return this.issuer.getPlayer();
    -044    }
    -045}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.bukkit.command.CommandSender;
    +027import org.bukkit.entity.Player;
    +028
    +029public class BukkitCommandCompletionContext extends CommandCompletionContext<BukkitCommandIssuer> {
    +030    BukkitCommandCompletionContext(RegisteredCommand command, BukkitCommandIssuer issuer, String input, String config, String[] args) {
    +031        super(command, issuer, input, config, args);
    +032    }
    +033
    +034    public CommandSender getSender() {
    +035        return this.getIssuer().getIssuer();
    +036    }
    +037
    +038    /**
    +039     * Returns the Player object if this Issuer is a Player
    +040     * @return
    +041     */
    +042    public Player getPlayer() {
    +043        return this.issuer.getPlayer();
    +044    }
    +045}
     
     
     
    @@ -113,5 +114,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandCompletions.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandCompletions.html index d927f0e7..b75ba38e 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandCompletions.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandCompletions.html @@ -1,106 +1,107 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.commands.bukkit.contexts.OnlinePlayer;
    -027import org.apache.commons.lang.Validate;
    -028import org.bukkit.Bukkit;
    -029import org.bukkit.ChatColor;
    -030import org.bukkit.DyeColor;
    -031import org.bukkit.World;
    -032import org.bukkit.command.CommandSender;
    -033import org.bukkit.entity.EntityType;
    -034import org.bukkit.entity.Player;
    -035import org.bukkit.util.StringUtil;
    -036
    -037import java.util.ArrayList;
    -038import java.util.Arrays;
    -039import java.util.Set;
    -040import java.util.stream.Collectors;
    -041import java.util.stream.Stream;
    -042
    -043@SuppressWarnings("WeakerAccess")
    -044public class BukkitCommandCompletions extends CommandCompletions<BukkitCommandCompletionContext> {
    -045    public BukkitCommandCompletions(BukkitCommandManager manager) {
    -046        super(manager);
    -047        registerAsyncCompletion("mobs", c -> {
    -048            final Stream<String> normal = Stream.of(EntityType.values())
    -049                    .map(entityType -> ACFUtil.simplifyString(entityType.getName()));
    -050            return normal.collect(Collectors.toList());
    -051        });
    -052        registerAsyncCompletion("chatcolors", c -> {
    -053            Stream<ChatColor> colors = Stream.of(ChatColor.values());
    -054            if (c.hasConfig("colorsonly")) {
    -055                colors = colors.filter(color -> color.ordinal() <= 0xF);
    -056            }
    -057            String filter = c.getConfig("filter");
    -058            if (filter != null) {
    -059                Set<String> filters = Arrays.stream(ACFPatterns.COLON.split(filter))
    -060                        .map(ACFUtil::simplifyString).collect(Collectors.toSet());
    -061
    -062                colors = colors.filter(color -> filters.contains(ACFUtil.simplifyString(color.name())));
    -063            }
    -064
    -065            return colors.map(color -> ACFUtil.simplifyString(color.name())).collect(Collectors.toList());
    -066        });
    -067        registerAsyncCompletion("dyecolors", c -> ACFUtil.enumNames(DyeColor.values()));
    -068        registerCompletion("worlds", c -> (
    -069                Bukkit.getWorlds().stream().map(World::getName).collect(Collectors.toList())
    -070        ));
    -071
    -072        registerCompletion("players", c -> {
    -073            CommandSender sender = c.getSender();
    -074            Validate.notNull(sender, "Sender cannot be null");
    -075
    -076            Player senderPlayer = sender instanceof Player ? (Player) sender : null;
    -077
    -078            ArrayList<String> matchedPlayers = new ArrayList<>();
    -079            for (Player player : Bukkit.getOnlinePlayers()) {
    -080                String name = player.getName();
    -081                if ((senderPlayer == null || senderPlayer.canSee(player)) && StringUtil.startsWithIgnoreCase(name, c.getInput())) {
    -082                    matchedPlayers.add(name);
    -083                }
    -084            }
    -085
    -086
    -087            matchedPlayers.sort(String.CASE_INSENSITIVE_ORDER);
    -088            return matchedPlayers;
    -089        });
    -090
    -091        setDefaultCompletion("players", OnlinePlayer.class, co.aikar.commands.contexts.OnlinePlayer.class, Player.class);
    -092        setDefaultCompletion("worlds", World.class);
    -093    }
    -094
    -095}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.commands.bukkit.contexts.OnlinePlayer;
    +027import org.apache.commons.lang.Validate;
    +028import org.bukkit.Bukkit;
    +029import org.bukkit.ChatColor;
    +030import org.bukkit.DyeColor;
    +031import org.bukkit.World;
    +032import org.bukkit.command.CommandSender;
    +033import org.bukkit.entity.EntityType;
    +034import org.bukkit.entity.Player;
    +035import org.bukkit.util.StringUtil;
    +036
    +037import java.util.ArrayList;
    +038import java.util.Arrays;
    +039import java.util.Set;
    +040import java.util.stream.Collectors;
    +041import java.util.stream.Stream;
    +042
    +043@SuppressWarnings("WeakerAccess")
    +044public class BukkitCommandCompletions extends CommandCompletions<BukkitCommandCompletionContext> {
    +045    public BukkitCommandCompletions(BukkitCommandManager manager) {
    +046        super(manager);
    +047        registerAsyncCompletion("mobs", c -> {
    +048            final Stream<String> normal = Stream.of(EntityType.values())
    +049                    .map(entityType -> ACFUtil.simplifyString(entityType.getName()));
    +050            return normal.collect(Collectors.toList());
    +051        });
    +052        registerAsyncCompletion("chatcolors", c -> {
    +053            Stream<ChatColor> colors = Stream.of(ChatColor.values());
    +054            if (c.hasConfig("colorsonly")) {
    +055                colors = colors.filter(color -> color.ordinal() <= 0xF);
    +056            }
    +057            String filter = c.getConfig("filter");
    +058            if (filter != null) {
    +059                Set<String> filters = Arrays.stream(ACFPatterns.COLON.split(filter))
    +060                        .map(ACFUtil::simplifyString).collect(Collectors.toSet());
    +061
    +062                colors = colors.filter(color -> filters.contains(ACFUtil.simplifyString(color.name())));
    +063            }
    +064
    +065            return colors.map(color -> ACFUtil.simplifyString(color.name())).collect(Collectors.toList());
    +066        });
    +067        registerAsyncCompletion("dyecolors", c -> ACFUtil.enumNames(DyeColor.values()));
    +068        registerCompletion("worlds", c -> (
    +069                Bukkit.getWorlds().stream().map(World::getName).collect(Collectors.toList())
    +070        ));
    +071
    +072        registerCompletion("players", c -> {
    +073            CommandSender sender = c.getSender();
    +074            Validate.notNull(sender, "Sender cannot be null");
    +075
    +076            Player senderPlayer = sender instanceof Player ? (Player) sender : null;
    +077
    +078            ArrayList<String> matchedPlayers = new ArrayList<>();
    +079            for (Player player : Bukkit.getOnlinePlayers()) {
    +080                String name = player.getName();
    +081                if ((senderPlayer == null || senderPlayer.canSee(player)) && StringUtil.startsWithIgnoreCase(name, c.getInput())) {
    +082                    matchedPlayers.add(name);
    +083                }
    +084            }
    +085
    +086
    +087            matchedPlayers.sort(String.CASE_INSENSITIVE_ORDER);
    +088            return matchedPlayers;
    +089        });
    +090
    +091        setDefaultCompletion("players", OnlinePlayer.class, co.aikar.commands.contexts.OnlinePlayer.class, Player.class);
    +092        setDefaultCompletion("worlds", World.class);
    +093    }
    +094
    +095}
     
     
     
    @@ -163,5 +164,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandContexts.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandContexts.html index 515066e7..be0060ac 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandContexts.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandContexts.html @@ -1,262 +1,263 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.commands.bukkit.contexts.OnlinePlayer;
    -027import org.bukkit.Bukkit;
    -028import org.bukkit.ChatColor;
    -029import org.bukkit.Location;
    -030import org.bukkit.OfflinePlayer;
    -031import org.bukkit.World;
    -032import org.bukkit.command.BlockCommandSender;
    -033import org.bukkit.command.CommandSender;
    -034import org.bukkit.entity.Entity;
    -035import org.bukkit.entity.Player;
    -036import org.bukkit.inventory.PlayerInventory;
    -037import org.jetbrains.annotations.Nullable;
    -038
    -039import java.util.HashSet;
    -040import java.util.Set;
    -041import java.util.UUID;
    -042import java.util.regex.Pattern;
    -043import java.util.stream.Collectors;
    -044import java.util.stream.Stream;
    -045
    -046@SuppressWarnings("WeakerAccess")
    -047public class BukkitCommandContexts extends CommandContexts<BukkitCommandExecutionContext> {
    -048
    -049    public BukkitCommandContexts(BukkitCommandManager manager) {
    -050        super(manager);
    -051
    -052        registerContext(OnlinePlayer.class, c -> getOnlinePlayer(c.getIssuer(), c.popFirstArg(), c.isOptional()));
    -053        registerContext(co.aikar.commands.contexts.OnlinePlayer.class, c -> {
    -054            OnlinePlayer onlinePlayer = getOnlinePlayer(c.getIssuer(), c.popFirstArg(), c.isOptional());
    -055            return onlinePlayer != null ? new co.aikar.commands.contexts.OnlinePlayer(onlinePlayer.getPlayer()) : null;
    -056        });
    -057        registerContext(OnlinePlayer[].class, (c) -> {
    -058            BukkitCommandIssuer issuer = c.getIssuer();
    -059            final String search = c.popFirstArg();
    -060            boolean allowMissing = c.hasFlag("allowmissing");
    -061            Set<OnlinePlayer> players = new HashSet<>();
    -062            Pattern split = ACFPatterns.COMMA;
    -063            String splitter = c.getFlagValue("splitter", (String) null);
    -064            if (splitter != null) {
    -065                split = Pattern.compile(Pattern.quote(splitter));
    -066            }
    -067            for (String lookup : split.split(search)) {
    -068                OnlinePlayer player = getOnlinePlayer(issuer, lookup, allowMissing);
    -069                if (player != null) {
    -070                    players.add(player);
    -071                }
    -072            }
    -073            if (players.isEmpty() && !c.hasFlag("allowempty")) {
    -074                issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER,
    -075                        "{search}", search);
    -076
    -077                throw new InvalidCommandArgument(false);
    -078            }
    -079            return players.toArray(new OnlinePlayer[players.size()]);
    -080        });
    -081        registerIssuerAwareContext(World.class, (c) -> {
    -082            String firstArg = c.getFirstArg();
    -083            World world = firstArg != null ? Bukkit.getWorld(firstArg) : null;
    -084            if (world != null) {
    -085                c.popFirstArg();
    -086            }
    -087            if (world == null && c.getSender() instanceof Player) {
    -088                world = ((Entity) c.getSender()).getWorld();
    -089            }
    -090            if (world == null) {
    -091                throw new InvalidCommandArgument(MinecraftMessageKeys.INVALID_WORLD);
    -092            }
    -093            return world;
    -094        });
    -095        registerIssuerAwareContext(CommandSender.class, BukkitCommandExecutionContext::getSender);
    -096        registerIssuerAwareContext(Player.class, (c) -> {
    -097            boolean isOptional = c.isOptional();
    -098            CommandSender sender = c.getSender();
    -099            boolean isPlayerSender = sender instanceof Player;
    -100            if (!c.hasFlag("other")) {
    -101                Player player = isPlayerSender ? (Player) sender : null;
    -102                if (player == null && !isOptional) {
    -103                    throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
    -104                }
    -105                PlayerInventory inventory = player != null ? player.getInventory() : null;
    -106                if (inventory != null && c.hasFlag("itemheld") && !ACFBukkitUtil.isValidItem(inventory.getItem(inventory.getHeldItemSlot()))) {
    -107                    throw new InvalidCommandArgument(MinecraftMessageKeys.YOU_MUST_BE_HOLDING_ITEM, false);
    -108                }
    -109                return player;
    -110            } else {
    -111                String arg = c.popFirstArg();
    -112                if (arg == null && isOptional) {
    -113                    if (c.hasFlag("defaultself")) {
    -114                        if (isPlayerSender) {
    -115                            return (Player) sender;
    -116                        } else {
    -117                            throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
    -118                        }
    -119                    } else {
    -120                        return null;
    -121                    }
    -122                } else if (arg == null) {
    -123                    throw new InvalidCommandArgument();
    -124                }
    -125
    -126                OnlinePlayer onlinePlayer = getOnlinePlayer(c.getIssuer(), arg, isOptional);
    -127                return onlinePlayer != null ? onlinePlayer.getPlayer() : null;
    -128            }
    -129        });
    -130        registerContext(OfflinePlayer.class, c -> {
    -131            String name = c.popFirstArg();
    -132            UUID uuid = null;
    -133            if (c.hasFlag("uuid")) {
    -134                uuid = UUID.fromString(name);
    -135            }
    -136            OfflinePlayer offlinePlayer = uuid != null ? Bukkit.getOfflinePlayer(uuid) : Bukkit.getOfflinePlayer(name);
    -137            if (offlinePlayer == null || (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline())) {
    -138                throw new InvalidCommandArgument(MinecraftMessageKeys.NO_PLAYER_FOUND_OFFLINE,
    -139                        "{search}", name);
    -140            }
    -141            return offlinePlayer;
    -142        });
    -143        registerContext(ChatColor.class, c -> {
    -144            String first = c.popFirstArg();
    -145            Stream<ChatColor> colors = Stream.of(ChatColor.values());
    -146            if (c.hasFlag("colorsonly")) {
    -147                colors = colors.filter(color -> color.ordinal() <= 0xF);
    -148            }
    -149            String filter = c.getFlagValue("filter", (String) null);
    -150            if (filter != null) {
    -151                filter = ACFUtil.simplifyString(filter);
    -152                String finalFilter = filter;
    -153                colors = colors.filter(color -> finalFilter.equals(ACFUtil.simplifyString(color.name())));
    -154            }
    -155
    -156            ChatColor match = ACFUtil.simpleMatch(ChatColor.class, first);
    -157            if (match == null) {
    -158                String valid = colors
    -159                        .map(color -> "<c2>" + ACFUtil.simplifyString(color.name()) + "</c2>")
    -160                        .collect(Collectors.joining("<c1>,</c1> "));
    -161
    -162                throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
    -163            }
    -164            return match;
    -165        });
    -166        registerContext(Location.class, c -> {
    -167            String input = c.popFirstArg();
    -168            CommandSender sender = c.getSender();
    -169            String[] split = ACFPatterns.COLON.split(input, 2);
    -170            if (split.length == 0) {
    -171                throw new InvalidCommandArgument(true);
    -172            }
    -173            if (split.length < 2 && !(sender instanceof Player) && !(sender instanceof BlockCommandSender)) {
    -174                throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_WORLD);
    -175            }
    -176            final String world;
    -177            final String rest;
    -178            Location sourceLoc = null;
    -179            if (split.length == 2) {
    -180                world = split[0];
    -181                rest = split[1];
    -182            } else if (sender instanceof Player) {
    -183                sourceLoc = ((Player) sender).getLocation();
    -184                world = sourceLoc.getWorld().getName();
    -185                rest = split[0];
    -186            } else if (sender instanceof BlockCommandSender) {
    -187                sourceLoc = ((BlockCommandSender) sender).getBlock().getLocation();
    -188                world = sourceLoc.getWorld().getName();
    -189                rest = split[0];
    -190            } else {
    -191                throw new InvalidCommandArgument(true);
    -192            }
    -193
    -194            boolean rel = rest.startsWith("~");
    -195            split = ACFPatterns.COMMA.split(rel ? rest.substring(1) : rest);
    -196            if (split.length < 3) {
    -197                throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_XYZ);
    -198            }
    -199
    -200            Double x = ACFUtil.parseDouble(split[0]);
    -201            Double y = ACFUtil.parseDouble(split[1]);
    -202            Double z = ACFUtil.parseDouble(split[2]);
    -203
    -204            if (sourceLoc != null && rel) {
    -205                x += sourceLoc.getX();
    -206                y += sourceLoc.getY();
    -207                z += sourceLoc.getZ();
    -208            } else if (rel) {
    -209                throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_CONSOLE_NOT_RELATIVE);
    -210            }
    -211
    -212            if (x == null || y == null || z == null) {
    -213                throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_XYZ);
    -214            }
    -215
    -216            World worldObj = Bukkit.getWorld(world);
    -217            if (worldObj == null) {
    -218                throw new InvalidCommandArgument(MinecraftMessageKeys.INVALID_WORLD);
    -219            }
    -220
    -221            if (split.length >= 5) {
    -222                Float yaw = ACFUtil.parseFloat(split[3]);
    -223                Float pitch = ACFUtil.parseFloat(split[4]);
    -224
    -225                if (pitch == null || yaw == null) {
    -226                    throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_XYZ);
    -227                }
    -228                return new Location(worldObj, x, y, z, yaw, pitch);
    -229            } else {
    -230                return new Location(worldObj, x, y, z);
    -231            }
    -232        });
    -233
    -234        if (manager.mcMinorVersion >= 12) {
    -235            BukkitCommandContexts_1_12.register(this);
    -236        }
    -237    }
    -238
    -239    @Nullable
    -240    OnlinePlayer getOnlinePlayer(BukkitCommandIssuer issuer, String lookup, boolean allowMissing) throws InvalidCommandArgument {
    -241        Player player = ACFBukkitUtil.findPlayerSmart(issuer, lookup);
    -242        //noinspection Duplicates
    -243        if (player == null) {
    -244            if (allowMissing) {
    -245                return null;
    -246            }
    -247            throw new InvalidCommandArgument(false);
    -248        }
    -249        return new OnlinePlayer(player);
    -250    }
    -251}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.commands.bukkit.contexts.OnlinePlayer;
    +027import org.bukkit.Bukkit;
    +028import org.bukkit.ChatColor;
    +029import org.bukkit.Location;
    +030import org.bukkit.OfflinePlayer;
    +031import org.bukkit.World;
    +032import org.bukkit.command.BlockCommandSender;
    +033import org.bukkit.command.CommandSender;
    +034import org.bukkit.entity.Entity;
    +035import org.bukkit.entity.Player;
    +036import org.bukkit.inventory.PlayerInventory;
    +037import org.jetbrains.annotations.Nullable;
    +038
    +039import java.util.HashSet;
    +040import java.util.Set;
    +041import java.util.UUID;
    +042import java.util.regex.Pattern;
    +043import java.util.stream.Collectors;
    +044import java.util.stream.Stream;
    +045
    +046@SuppressWarnings("WeakerAccess")
    +047public class BukkitCommandContexts extends CommandContexts<BukkitCommandExecutionContext> {
    +048
    +049    public BukkitCommandContexts(BukkitCommandManager manager) {
    +050        super(manager);
    +051
    +052        registerContext(OnlinePlayer.class, c -> getOnlinePlayer(c.getIssuer(), c.popFirstArg(), c.isOptional()));
    +053        registerContext(co.aikar.commands.contexts.OnlinePlayer.class, c -> {
    +054            OnlinePlayer onlinePlayer = getOnlinePlayer(c.getIssuer(), c.popFirstArg(), c.isOptional());
    +055            return onlinePlayer != null ? new co.aikar.commands.contexts.OnlinePlayer(onlinePlayer.getPlayer()) : null;
    +056        });
    +057        registerContext(OnlinePlayer[].class, (c) -> {
    +058            BukkitCommandIssuer issuer = c.getIssuer();
    +059            final String search = c.popFirstArg();
    +060            boolean allowMissing = c.hasFlag("allowmissing");
    +061            Set<OnlinePlayer> players = new HashSet<>();
    +062            Pattern split = ACFPatterns.COMMA;
    +063            String splitter = c.getFlagValue("splitter", (String) null);
    +064            if (splitter != null) {
    +065                split = Pattern.compile(Pattern.quote(splitter));
    +066            }
    +067            for (String lookup : split.split(search)) {
    +068                OnlinePlayer player = getOnlinePlayer(issuer, lookup, allowMissing);
    +069                if (player != null) {
    +070                    players.add(player);
    +071                }
    +072            }
    +073            if (players.isEmpty() && !c.hasFlag("allowempty")) {
    +074                issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER,
    +075                        "{search}", search);
    +076
    +077                throw new InvalidCommandArgument(false);
    +078            }
    +079            return players.toArray(new OnlinePlayer[players.size()]);
    +080        });
    +081        registerIssuerAwareContext(World.class, (c) -> {
    +082            String firstArg = c.getFirstArg();
    +083            World world = firstArg != null ? Bukkit.getWorld(firstArg) : null;
    +084            if (world != null) {
    +085                c.popFirstArg();
    +086            }
    +087            if (world == null && c.getSender() instanceof Player) {
    +088                world = ((Entity) c.getSender()).getWorld();
    +089            }
    +090            if (world == null) {
    +091                throw new InvalidCommandArgument(MinecraftMessageKeys.INVALID_WORLD);
    +092            }
    +093            return world;
    +094        });
    +095        registerIssuerAwareContext(CommandSender.class, BukkitCommandExecutionContext::getSender);
    +096        registerIssuerAwareContext(Player.class, (c) -> {
    +097            boolean isOptional = c.isOptional();
    +098            CommandSender sender = c.getSender();
    +099            boolean isPlayerSender = sender instanceof Player;
    +100            if (!c.hasFlag("other")) {
    +101                Player player = isPlayerSender ? (Player) sender : null;
    +102                if (player == null && !isOptional) {
    +103                    throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
    +104                }
    +105                PlayerInventory inventory = player != null ? player.getInventory() : null;
    +106                if (inventory != null && c.hasFlag("itemheld") && !ACFBukkitUtil.isValidItem(inventory.getItem(inventory.getHeldItemSlot()))) {
    +107                    throw new InvalidCommandArgument(MinecraftMessageKeys.YOU_MUST_BE_HOLDING_ITEM, false);
    +108                }
    +109                return player;
    +110            } else {
    +111                String arg = c.popFirstArg();
    +112                if (arg == null && isOptional) {
    +113                    if (c.hasFlag("defaultself")) {
    +114                        if (isPlayerSender) {
    +115                            return (Player) sender;
    +116                        } else {
    +117                            throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
    +118                        }
    +119                    } else {
    +120                        return null;
    +121                    }
    +122                } else if (arg == null) {
    +123                    throw new InvalidCommandArgument();
    +124                }
    +125
    +126                OnlinePlayer onlinePlayer = getOnlinePlayer(c.getIssuer(), arg, isOptional);
    +127                return onlinePlayer != null ? onlinePlayer.getPlayer() : null;
    +128            }
    +129        });
    +130        registerContext(OfflinePlayer.class, c -> {
    +131            String name = c.popFirstArg();
    +132            UUID uuid = null;
    +133            if (c.hasFlag("uuid")) {
    +134                uuid = UUID.fromString(name);
    +135            }
    +136            OfflinePlayer offlinePlayer = uuid != null ? Bukkit.getOfflinePlayer(uuid) : Bukkit.getOfflinePlayer(name);
    +137            if (offlinePlayer == null || (!offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline())) {
    +138                throw new InvalidCommandArgument(MinecraftMessageKeys.NO_PLAYER_FOUND_OFFLINE,
    +139                        "{search}", name);
    +140            }
    +141            return offlinePlayer;
    +142        });
    +143        registerContext(ChatColor.class, c -> {
    +144            String first = c.popFirstArg();
    +145            Stream<ChatColor> colors = Stream.of(ChatColor.values());
    +146            if (c.hasFlag("colorsonly")) {
    +147                colors = colors.filter(color -> color.ordinal() <= 0xF);
    +148            }
    +149            String filter = c.getFlagValue("filter", (String) null);
    +150            if (filter != null) {
    +151                filter = ACFUtil.simplifyString(filter);
    +152                String finalFilter = filter;
    +153                colors = colors.filter(color -> finalFilter.equals(ACFUtil.simplifyString(color.name())));
    +154            }
    +155
    +156            ChatColor match = ACFUtil.simpleMatch(ChatColor.class, first);
    +157            if (match == null) {
    +158                String valid = colors
    +159                        .map(color -> "<c2>" + ACFUtil.simplifyString(color.name()) + "</c2>")
    +160                        .collect(Collectors.joining("<c1>,</c1> "));
    +161
    +162                throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
    +163            }
    +164            return match;
    +165        });
    +166        registerContext(Location.class, c -> {
    +167            String input = c.popFirstArg();
    +168            CommandSender sender = c.getSender();
    +169            String[] split = ACFPatterns.COLON.split(input, 2);
    +170            if (split.length == 0) {
    +171                throw new InvalidCommandArgument(true);
    +172            }
    +173            if (split.length < 2 && !(sender instanceof Player) && !(sender instanceof BlockCommandSender)) {
    +174                throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_WORLD);
    +175            }
    +176            final String world;
    +177            final String rest;
    +178            Location sourceLoc = null;
    +179            if (split.length == 2) {
    +180                world = split[0];
    +181                rest = split[1];
    +182            } else if (sender instanceof Player) {
    +183                sourceLoc = ((Player) sender).getLocation();
    +184                world = sourceLoc.getWorld().getName();
    +185                rest = split[0];
    +186            } else if (sender instanceof BlockCommandSender) {
    +187                sourceLoc = ((BlockCommandSender) sender).getBlock().getLocation();
    +188                world = sourceLoc.getWorld().getName();
    +189                rest = split[0];
    +190            } else {
    +191                throw new InvalidCommandArgument(true);
    +192            }
    +193
    +194            boolean rel = rest.startsWith("~");
    +195            split = ACFPatterns.COMMA.split(rel ? rest.substring(1) : rest);
    +196            if (split.length < 3) {
    +197                throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_XYZ);
    +198            }
    +199
    +200            Double x = ACFUtil.parseDouble(split[0]);
    +201            Double y = ACFUtil.parseDouble(split[1]);
    +202            Double z = ACFUtil.parseDouble(split[2]);
    +203
    +204            if (sourceLoc != null && rel) {
    +205                x += sourceLoc.getX();
    +206                y += sourceLoc.getY();
    +207                z += sourceLoc.getZ();
    +208            } else if (rel) {
    +209                throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_CONSOLE_NOT_RELATIVE);
    +210            }
    +211
    +212            if (x == null || y == null || z == null) {
    +213                throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_XYZ);
    +214            }
    +215
    +216            World worldObj = Bukkit.getWorld(world);
    +217            if (worldObj == null) {
    +218                throw new InvalidCommandArgument(MinecraftMessageKeys.INVALID_WORLD);
    +219            }
    +220
    +221            if (split.length >= 5) {
    +222                Float yaw = ACFUtil.parseFloat(split[3]);
    +223                Float pitch = ACFUtil.parseFloat(split[4]);
    +224
    +225                if (pitch == null || yaw == null) {
    +226                    throw new InvalidCommandArgument(MinecraftMessageKeys.LOCATION_PLEASE_SPECIFY_XYZ);
    +227                }
    +228                return new Location(worldObj, x, y, z, yaw, pitch);
    +229            } else {
    +230                return new Location(worldObj, x, y, z);
    +231            }
    +232        });
    +233
    +234        if (manager.mcMinorVersion >= 12) {
    +235            BukkitCommandContexts_1_12.register(this);
    +236        }
    +237    }
    +238
    +239    @Nullable
    +240    OnlinePlayer getOnlinePlayer(BukkitCommandIssuer issuer, String lookup, boolean allowMissing) throws InvalidCommandArgument {
    +241        Player player = ACFBukkitUtil.findPlayerSmart(issuer, lookup);
    +242        //noinspection Duplicates
    +243        if (player == null) {
    +244            if (allowMissing) {
    +245                return null;
    +246            }
    +247            throw new InvalidCommandArgument(false);
    +248        }
    +249        return new OnlinePlayer(player);
    +250    }
    +251}
     
     
     
    @@ -319,5 +320,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandExecutionContext.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandExecutionContext.html index 616b557d..68bc6682 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandExecutionContext.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandExecutionContext.html @@ -1,60 +1,61 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.bukkit.command.CommandSender;
    -027import org.bukkit.entity.Player;
    -028
    -029import java.util.List;
    -030import java.util.Map;
    -031
    -032public class BukkitCommandExecutionContext extends CommandExecutionContext<BukkitCommandExecutionContext, BukkitCommandIssuer> {
    -033    BukkitCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, BukkitCommandIssuer sender, List<String> args,
    -034                                  int index, Map<String, Object> passedArgs) {
    -035        super(cmd, param, sender, args, index, passedArgs);
    -036    }
    -037
    -038    public CommandSender getSender() {
    -039        return this.issuer.getIssuer();
    -040    }
    -041
    -042    /**
    -043     * Returns the Player object if this Issuer is a Player
    -044     * @return
    -045     */
    -046    public Player getPlayer() {
    -047        return this.issuer.getPlayer();
    -048    }
    -049}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.bukkit.command.CommandSender;
    +027import org.bukkit.entity.Player;
    +028
    +029import java.util.List;
    +030import java.util.Map;
    +031
    +032public class BukkitCommandExecutionContext extends CommandExecutionContext<BukkitCommandExecutionContext, BukkitCommandIssuer> {
    +033    BukkitCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, BukkitCommandIssuer sender, List<String> args,
    +034                                  int index, Map<String, Object> passedArgs) {
    +035        super(cmd, param, sender, args, index, passedArgs);
    +036    }
    +037
    +038    public CommandSender getSender() {
    +039        return this.issuer.getIssuer();
    +040    }
    +041
    +042    /**
    +043     * Returns the Player object if this Issuer is a Player
    +044     * @return
    +045     */
    +046    public Player getPlayer() {
    +047        return this.issuer.getPlayer();
    +048    }
    +049}
     
     
     
    @@ -117,5 +118,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandIssuer.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandIssuer.html index f738890a..fa9b55ef 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandIssuer.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandIssuer.html @@ -1,106 +1,107 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.bukkit.command.CommandSender;
    -027import org.bukkit.entity.Player;
    -028import org.jetbrains.annotations.NotNull;
    -029
    -030import java.nio.charset.StandardCharsets;
    -031import java.util.Objects;
    -032import java.util.UUID;
    -033
    -034public class BukkitCommandIssuer implements CommandIssuer {
    -035    private final BukkitCommandManager manager;
    -036    private final CommandSender sender;
    -037
    -038    BukkitCommandIssuer(BukkitCommandManager manager, CommandSender sender) {
    -039        this.manager = manager;
    -040        this.sender = sender;
    -041    }
    -042
    -043    @Override
    -044    public boolean isPlayer() {
    -045        return sender instanceof Player;
    -046    }
    -047
    -048    @Override
    -049    public CommandSender getIssuer() {
    -050        //noinspection unchecked
    -051        return sender;
    -052    }
    -053
    -054    public Player getPlayer() {
    -055        return isPlayer() ? (Player) sender : null;
    -056    }
    -057
    -058    @Override
    -059    public @NotNull UUID getUniqueId() {
    -060        if (isPlayer()) {
    -061            return ((Player) sender).getUniqueId();
    -062        }
    -063
    -064        //generate a unique id based of the name (like for the console command sender)
    -065        return UUID.nameUUIDFromBytes(sender.getName().getBytes(StandardCharsets.UTF_8));
    -066    }
    -067
    -068    @Override
    -069    public CommandManager getManager() {
    -070        return manager;
    -071    }
    -072
    -073    @Override
    -074    public void sendMessageInternal(String message) {
    -075        sender.sendMessage(ACFBukkitUtil.color(message));
    -076    }
    -077
    -078    @Override
    -079    public boolean hasPermission(String name) {
    -080        return sender.hasPermission(name);
    -081    }
    -082
    -083    @Override
    -084    public boolean equals(Object o) {
    -085        if (this == o) return true;
    -086        if (o == null || getClass() != o.getClass()) return false;
    -087        BukkitCommandIssuer that = (BukkitCommandIssuer) o;
    -088        return Objects.equals(sender, that.sender);
    -089    }
    -090
    -091    @Override
    -092    public int hashCode() {
    -093        return Objects.hash(sender);
    -094    }
    -095}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.bukkit.command.CommandSender;
    +027import org.bukkit.entity.Player;
    +028import org.jetbrains.annotations.NotNull;
    +029
    +030import java.nio.charset.StandardCharsets;
    +031import java.util.Objects;
    +032import java.util.UUID;
    +033
    +034public class BukkitCommandIssuer implements CommandIssuer {
    +035    private final BukkitCommandManager manager;
    +036    private final CommandSender sender;
    +037
    +038    BukkitCommandIssuer(BukkitCommandManager manager, CommandSender sender) {
    +039        this.manager = manager;
    +040        this.sender = sender;
    +041    }
    +042
    +043    @Override
    +044    public boolean isPlayer() {
    +045        return sender instanceof Player;
    +046    }
    +047
    +048    @Override
    +049    public CommandSender getIssuer() {
    +050        //noinspection unchecked
    +051        return sender;
    +052    }
    +053
    +054    public Player getPlayer() {
    +055        return isPlayer() ? (Player) sender : null;
    +056    }
    +057
    +058    @Override
    +059    public @NotNull UUID getUniqueId() {
    +060        if (isPlayer()) {
    +061            return ((Player) sender).getUniqueId();
    +062        }
    +063
    +064        //generate a unique id based of the name (like for the console command sender)
    +065        return UUID.nameUUIDFromBytes(sender.getName().getBytes(StandardCharsets.UTF_8));
    +066    }
    +067
    +068    @Override
    +069    public CommandManager getManager() {
    +070        return manager;
    +071    }
    +072
    +073    @Override
    +074    public void sendMessageInternal(String message) {
    +075        sender.sendMessage(ACFBukkitUtil.color(message));
    +076    }
    +077
    +078    @Override
    +079    public boolean hasPermission(String name) {
    +080        return sender.hasPermission(name);
    +081    }
    +082
    +083    @Override
    +084    public boolean equals(Object o) {
    +085        if (this == o) return true;
    +086        if (o == null || getClass() != o.getClass()) return false;
    +087        BukkitCommandIssuer that = (BukkitCommandIssuer) o;
    +088        return Objects.equals(sender, that.sender);
    +089    }
    +090
    +091    @Override
    +092    public int hashCode() {
    +093        return Objects.hash(sender);
    +094    }
    +095}
     
     
     
    @@ -163,5 +164,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandManager.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandManager.html index 6279c4d1..42bafb43 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandManager.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitCommandManager.html @@ -1,416 +1,417 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    -027import co.aikar.timings.lib.MCTiming;
    -028import co.aikar.timings.lib.TimingManager;
    -029import org.bukkit.Bukkit;
    -030import org.bukkit.ChatColor;
    -031import org.bukkit.Server;
    -032import org.bukkit.command.Command;
    -033import org.bukkit.command.CommandException;
    -034import org.bukkit.command.CommandMap;
    -035import org.bukkit.command.CommandSender;
    -036import org.bukkit.command.PluginIdentifiableCommand;
    -037import org.bukkit.command.SimpleCommandMap;
    -038import org.bukkit.configuration.file.FileConfiguration;
    -039import org.bukkit.entity.Player;
    -040import org.bukkit.help.GenericCommandHelpTopic;
    -041import org.bukkit.inventory.ItemFactory;
    -042import org.bukkit.plugin.Plugin;
    -043import org.bukkit.plugin.PluginManager;
    -044import org.bukkit.plugin.java.JavaPlugin;
    -045import org.bukkit.scheduler.BukkitScheduler;
    -046import org.bukkit.scheduler.BukkitTask;
    -047import org.bukkit.scoreboard.ScoreboardManager;
    -048import org.jetbrains.annotations.NotNull;
    -049
    -050import java.lang.reflect.Field;
    -051import java.lang.reflect.Method;
    -052import java.util.Collection;
    -053import java.util.Collections;
    -054import java.util.HashMap;
    -055import java.util.HashSet;
    -056import java.util.List;
    -057import java.util.Locale;
    -058import java.util.Map;
    -059import java.util.Objects;
    -060import java.util.logging.Level;
    -061import java.util.logging.Logger;
    -062import java.util.regex.Matcher;
    -063import java.util.regex.Pattern;
    -064
    -065@SuppressWarnings("WeakerAccess")
    -066public class BukkitCommandManager extends CommandManager<
    -067        CommandSender,
    -068        BukkitCommandIssuer,
    -069        ChatColor,
    -070        BukkitMessageFormatter,
    -071        BukkitCommandExecutionContext,
    -072        BukkitConditionContext
    -073        > {
    -074
    -075    @SuppressWarnings("WeakerAccess")
    -076    protected final Plugin plugin;
    -077    private final CommandMap commandMap;
    -078    private final TimingManager timingManager;
    -079    private final BukkitTask localeTask;
    -080    private final Logger logger;
    -081    public final Integer mcMinorVersion;
    -082    public final Integer mcPatchVersion;
    -083    protected Map<String, Command> knownCommands = new HashMap<>();
    -084    protected Map<String, BukkitRootCommand> registeredCommands = new HashMap<>();
    -085    protected BukkitCommandContexts contexts;
    -086    protected BukkitCommandCompletions completions;
    -087    MCTiming commandTiming;
    -088    protected BukkitLocales locales;
    -089    private boolean cantReadLocale = false;
    -090    protected boolean autoDetectFromClient = true;
    -091
    -092    @SuppressWarnings("JavaReflectionMemberAccess")
    -093    public BukkitCommandManager(Plugin plugin) {
    -094        this.plugin = plugin;
    -095        this.logger = Logger.getLogger(this.plugin.getName());
    -096        this.timingManager = TimingManager.of(plugin);
    -097        this.commandTiming = this.timingManager.of("Commands");
    -098        this.commandMap = hookCommandMap();
    -099        this.formatters.put(MessageType.ERROR, defaultFormatter = new BukkitMessageFormatter(ChatColor.RED, ChatColor.YELLOW, ChatColor.RED));
    -100        this.formatters.put(MessageType.SYNTAX, new BukkitMessageFormatter(ChatColor.YELLOW, ChatColor.GREEN, ChatColor.WHITE));
    -101        this.formatters.put(MessageType.INFO, new BukkitMessageFormatter(ChatColor.BLUE, ChatColor.DARK_GREEN, ChatColor.GREEN));
    -102        this.formatters.put(MessageType.HELP, new BukkitMessageFormatter(ChatColor.AQUA, ChatColor.GREEN, ChatColor.YELLOW));
    -103        Pattern versionPattern = Pattern.compile("\\(MC: (\\d)\\.(\\d+)\\.?(\\d+?)?\\)");
    -104        Matcher matcher = versionPattern.matcher(Bukkit.getVersion());
    -105        if (matcher.find()) {
    -106            this.mcMinorVersion = ACFUtil.parseInt(matcher.toMatchResult().group(2), 0);
    -107            this.mcPatchVersion = ACFUtil.parseInt(matcher.toMatchResult().group(3), 0);
    -108        } else {
    -109            this.mcMinorVersion = -1;
    -110            this.mcPatchVersion = -1;
    -111        }
    -112        Bukkit.getHelpMap().registerHelpTopicFactory(BukkitRootCommand.class, command -> {
    -113            if (hasUnstableAPI("help")) {
    -114                return new ACFBukkitHelpTopic(this, (BukkitRootCommand) command);
    -115            } else {
    -116                return new GenericCommandHelpTopic(command);
    -117            }
    -118        });
    -119
    -120        Bukkit.getPluginManager().registerEvents(new ACFBukkitListener(this, plugin), plugin);
    -121
    -122        getLocales(); // auto load locales
    -123        this.localeTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
    -124            if (this.cantReadLocale || !this.autoDetectFromClient) {
    -125                return;
    -126            }
    -127            Bukkit.getOnlinePlayers().forEach(this::readPlayerLocale);
    -128        }, 5, 5);
    -129
    -130        registerDependency(plugin.getClass(), plugin);
    -131        registerDependency(Logger.class, plugin.getLogger());
    -132        registerDependency(FileConfiguration.class, plugin.getConfig());
    -133        registerDependency(FileConfiguration.class, "config", plugin.getConfig());
    -134        registerDependency(Plugin.class, plugin);
    -135        registerDependency(JavaPlugin.class, plugin);
    -136        registerDependency(PluginManager.class, Bukkit.getPluginManager());
    -137        registerDependency(Server.class, Bukkit.getServer());
    -138        registerDependency(BukkitScheduler.class, Bukkit.getScheduler());
    -139        registerDependency(ScoreboardManager.class, Bukkit.getScoreboardManager());
    -140        registerDependency(ItemFactory.class, Bukkit.getItemFactory());
    -141    }
    -142
    -143    @NotNull
    -144    private CommandMap hookCommandMap() {
    -145        CommandMap commandMap = null;
    -146        try {
    -147            Server server = Bukkit.getServer();
    -148            Method getCommandMap = server.getClass().getDeclaredMethod("getCommandMap");
    -149            getCommandMap.setAccessible(true);
    -150            commandMap = (CommandMap) getCommandMap.invoke(server);
    -151            if (!SimpleCommandMap.class.isAssignableFrom(commandMap.getClass())) {
    -152                this.log(LogLevel.ERROR, "ERROR: CommandMap has been hijacked! Offending command map is located at: " + commandMap.getClass().getName());
    -153                this.log(LogLevel.ERROR, "We are going to try to hijack it back and resolve this, but you are now in dangerous territory.");
    -154                this.log(LogLevel.ERROR, "We can not guarantee things are going to work.");
    -155                Field cmField = server.getClass().getDeclaredField("commandMap");
    -156                commandMap = new ProxyCommandMap(this, commandMap);
    -157                cmField.set(server, commandMap);
    -158                this.log(LogLevel.INFO, "Injected Proxy Command Map... good luck...");
    -159            }
    -160            Field knownCommands = SimpleCommandMap.class.getDeclaredField("knownCommands");
    -161            knownCommands.setAccessible(true);
    -162            //noinspection unchecked
    -163            this.knownCommands = (Map<String, Command>) knownCommands.get(commandMap);
    -164        } catch (Exception e) {
    -165            this.log(LogLevel.ERROR, "Failed to get Command Map. ACF will not function.");
    -166            ACFUtil.sneaky(e);
    -167        }
    -168        return commandMap;
    -169    }
    -170
    -171    public Plugin getPlugin() {
    -172        return this.plugin;
    -173    }
    -174
    -175    @Override
    -176    public boolean isCommandIssuer(Class<?> type) {
    -177        return CommandSender.class.isAssignableFrom(type);
    -178    }
    -179
    -180    @Override
    -181    public synchronized CommandContexts<BukkitCommandExecutionContext> getCommandContexts() {
    -182        if (this.contexts == null) {
    -183            this.contexts = new BukkitCommandContexts(this);
    -184        }
    -185        return contexts;
    -186    }
    -187
    -188    @Override
    -189    public synchronized CommandCompletions<BukkitCommandCompletionContext> getCommandCompletions() {
    -190        if (this.completions == null) {
    -191            this.completions = new BukkitCommandCompletions(this);
    -192        }
    -193        return completions;
    -194    }
    -195
    -196
    -197    @Override
    -198    public BukkitLocales getLocales() {
    -199        if (this.locales == null) {
    -200            this.locales = new BukkitLocales(this);
    -201            this.locales.loadLanguages();
    -202        }
    -203        return locales;
    -204    }
    -205
    -206
    -207    @Override
    -208    public boolean hasRegisteredCommands() {
    -209        return !registeredCommands.isEmpty();
    -210    }
    -211
    -212    public void registerCommand(BaseCommand command, boolean force) {
    -213        final String plugin = this.plugin.getName().toLowerCase();
    -214        command.onRegister(this);
    -215        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    -216            String commandName = entry.getKey().toLowerCase();
    -217            BukkitRootCommand bukkitCommand = (BukkitRootCommand) entry.getValue();
    -218            if (!bukkitCommand.isRegistered) {
    -219                Command oldCommand = commandMap.getCommand(commandName);
    -220                if (oldCommand instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) oldCommand).getPlugin() == this.plugin) {
    -221                    knownCommands.remove(commandName);
    -222                    oldCommand.unregister(commandMap);
    -223                } else if (oldCommand != null && force) {
    -224                    knownCommands.remove(commandName);
    -225                    for (Map.Entry<String, Command> ce : knownCommands.entrySet()) {
    -226                        String key = ce.getKey();
    -227                        Command value = ce.getValue();
    -228                        if (key.contains(":") && oldCommand.equals(value)) {
    -229                            String[] split = ACFPatterns.COLON.split(key, 2);
    -230                            if (split.length > 1) {
    -231                                oldCommand.unregister(commandMap);
    -232                                oldCommand.setLabel(split[0] + ":" + command.getName());
    -233                                oldCommand.register(commandMap);
    -234                            }
    -235                        }
    -236                    }
    -237                }
    -238                commandMap.register(commandName, plugin, bukkitCommand);
    -239            }
    -240            bukkitCommand.isRegistered = true;
    -241            registeredCommands.put(commandName, bukkitCommand);
    -242        }
    -243    }
    -244
    -245    @Override
    -246    public void registerCommand(BaseCommand command) {
    -247        registerCommand(command, false);
    -248    }
    -249
    -250    public void unregisterCommand(BaseCommand command) {
    -251        for (RootCommand rootcommand : command.registeredCommands.values()) {
    -252            BukkitRootCommand bukkitCommand = (BukkitRootCommand) rootcommand;
    -253            bukkitCommand.getSubCommands().values().removeAll(command.subCommands.values());
    -254            if (bukkitCommand.isRegistered && bukkitCommand.getSubCommands().isEmpty()) {
    -255                unregisterCommand(bukkitCommand);
    -256                bukkitCommand.isRegistered = false;
    -257            }
    -258        }
    -259    }
    -260
    -261    /**
    -262     * @param command
    -263     * @deprecated Use unregisterCommand(BaseCommand) - this will be visibility reduced later.
    -264     */
    -265    @Deprecated
    -266    public void unregisterCommand(BukkitRootCommand command) {
    -267        final String plugin = this.plugin.getName().toLowerCase();
    -268        command.unregister(commandMap);
    -269        String key = command.getName();
    -270        Command registered = knownCommands.get(key);
    -271        if (command.equals(registered)) {
    -272            knownCommands.remove(key);
    -273        }
    -274        knownCommands.remove(plugin + ":" + key);
    -275        registeredCommands.remove(key);
    -276    }
    -277
    -278    public void unregisterCommands() {
    -279        for (String key : new HashSet<>(registeredCommands.keySet())) {
    -280            unregisterCommand(registeredCommands.get(key));
    -281        }
    -282    }
    -283
    -284
    -285    private Field getEntityField(Player player) throws NoSuchFieldException {
    -286        Class cls = player.getClass();
    -287        while (cls != Object.class) {
    -288            if (cls.getName().endsWith("CraftEntity")) {
    -289                Field field = cls.getDeclaredField("entity");
    -290                field.setAccessible(true);
    -291                return field;
    -292            }
    -293            cls = cls.getSuperclass();
    -294        }
    -295        return null;
    -296    }
    -297
    -298    public Locale setPlayerLocale(Player player, Locale locale) {
    -299        return this.setIssuerLocale(player, locale);
    -300    }
    -301
    -302    void readPlayerLocale(Player player) {
    -303        if (!player.isOnline() || cantReadLocale) {
    -304            return;
    -305        }
    -306        try {
    -307            Field entityField = getEntityField(player);
    -308            if (entityField == null) {
    -309                return;
    -310            }
    -311            Object nmsPlayer = entityField.get(player);
    -312            if (nmsPlayer != null) {
    -313                Field localeField = nmsPlayer.getClass().getDeclaredField("locale");
    -314                localeField.setAccessible(true);
    -315                Object localeString = localeField.get(nmsPlayer);
    -316                if (localeString instanceof String) {
    -317                    String[] split = ACFPatterns.UNDERSCORE.split((String) localeString);
    -318                    Locale locale = split.length > 1 ? new Locale(split[0], split[1]) : new Locale(split[0]);
    -319                    Locale prev = issuersLocale.put(player.getUniqueId(), locale);
    -320                    if (!Objects.equals(locale, prev)) {
    -321                        this.notifyLocaleChange(getCommandIssuer(player), prev, locale);
    -322                    }
    -323                }
    -324            }
    -325        } catch (Exception e) {
    -326            cantReadLocale = true;
    -327            this.localeTask.cancel();
    -328            this.log(LogLevel.INFO, "Can't read players locale, you will be unable to automatically detect players language. Only Bukkit 1.7+ is supported for this.", e);
    -329        }
    -330    }
    -331
    -332    public TimingManager getTimings() {
    -333        return timingManager;
    -334    }
    -335
    -336    @Override
    -337    public RootCommand createRootCommand(String cmd) {
    -338        return new BukkitRootCommand(this, cmd);
    -339    }
    -340
    -341    @Override
    -342    public Collection<RootCommand> getRegisteredRootCommands() {
    -343        return Collections.unmodifiableCollection(registeredCommands.values());
    -344    }
    -345
    -346    @Override
    -347    public BukkitCommandIssuer getCommandIssuer(Object issuer) {
    -348        if (!(issuer instanceof CommandSender)) {
    -349            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
    -350        }
    -351        return new BukkitCommandIssuer(this, (CommandSender) issuer);
    -352    }
    -353
    -354    @Override
    -355    public BukkitCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
    -356        return new BukkitCommandExecutionContext(command, parameter, (BukkitCommandIssuer) sender, args, i, passedArgs);
    -357    }
    -358
    -359    @Override
    -360    public BukkitCommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
    -361        return new BukkitCommandCompletionContext(command, (BukkitCommandIssuer) sender, input, config, args);
    -362    }
    -363
    -364    @Override
    -365    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
    -366        return new BukkitRegisteredCommand(command, cmdName, method, prefSubCommand);
    -367    }
    -368
    -369    @Override
    -370    public BukkitConditionContext createConditionContext(CommandIssuer issuer, String config) {
    -371        return new BukkitConditionContext((BukkitCommandIssuer) issuer, config);
    -372    }
    -373
    -374
    -375    @Override
    -376    public void log(LogLevel level, String message, Throwable throwable) {
    -377        Level logLevel = level == LogLevel.INFO ? Level.INFO : Level.SEVERE;
    -378        logger.log(logLevel, LogLevel.LOG_PREFIX + message);
    -379        if (throwable != null) {
    -380            for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    -381                logger.log(logLevel, LogLevel.LOG_PREFIX + line);
    -382            }
    -383        }
    -384    }
    -385
    -386    public boolean usePerIssuerLocale(boolean usePerIssuerLocale, boolean autoDetectFromClient) {
    -387        boolean old = this.usePerIssuerLocale;
    -388        this.usePerIssuerLocale = usePerIssuerLocale;
    -389        this.autoDetectFromClient = autoDetectFromClient;
    -390        return old;
    -391    }
    -392
    -393    @Override
    -394    public String getCommandPrefix(CommandIssuer issuer) {
    -395        return issuer.isPlayer() ? "/" : "";
    -396    }
    -397
    -398    @Override
    -399    protected boolean handleUncaughtException(BaseCommand scope, RegisteredCommand registeredCommand, CommandIssuer sender, List<String> args, Throwable t) {
    -400        if (t instanceof CommandException && t.getCause() != null && t.getMessage().startsWith("Unhandled exception")) {
    -401            t = t.getCause();
    -402        }
    -403        return super.handleUncaughtException(scope, registeredCommand, sender, args, t);
    -404    }
    -405}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    +027import co.aikar.timings.lib.MCTiming;
    +028import co.aikar.timings.lib.TimingManager;
    +029import org.bukkit.Bukkit;
    +030import org.bukkit.ChatColor;
    +031import org.bukkit.Server;
    +032import org.bukkit.command.Command;
    +033import org.bukkit.command.CommandException;
    +034import org.bukkit.command.CommandMap;
    +035import org.bukkit.command.CommandSender;
    +036import org.bukkit.command.PluginIdentifiableCommand;
    +037import org.bukkit.command.SimpleCommandMap;
    +038import org.bukkit.configuration.file.FileConfiguration;
    +039import org.bukkit.entity.Player;
    +040import org.bukkit.help.GenericCommandHelpTopic;
    +041import org.bukkit.inventory.ItemFactory;
    +042import org.bukkit.plugin.Plugin;
    +043import org.bukkit.plugin.PluginManager;
    +044import org.bukkit.plugin.java.JavaPlugin;
    +045import org.bukkit.scheduler.BukkitScheduler;
    +046import org.bukkit.scheduler.BukkitTask;
    +047import org.bukkit.scoreboard.ScoreboardManager;
    +048import org.jetbrains.annotations.NotNull;
    +049
    +050import java.lang.reflect.Field;
    +051import java.lang.reflect.Method;
    +052import java.util.Collection;
    +053import java.util.Collections;
    +054import java.util.HashMap;
    +055import java.util.HashSet;
    +056import java.util.List;
    +057import java.util.Locale;
    +058import java.util.Map;
    +059import java.util.Objects;
    +060import java.util.logging.Level;
    +061import java.util.logging.Logger;
    +062import java.util.regex.Matcher;
    +063import java.util.regex.Pattern;
    +064
    +065@SuppressWarnings("WeakerAccess")
    +066public class BukkitCommandManager extends CommandManager<
    +067        CommandSender,
    +068        BukkitCommandIssuer,
    +069        ChatColor,
    +070        BukkitMessageFormatter,
    +071        BukkitCommandExecutionContext,
    +072        BukkitConditionContext
    +073        > {
    +074
    +075    @SuppressWarnings("WeakerAccess")
    +076    protected final Plugin plugin;
    +077    private final CommandMap commandMap;
    +078    private final TimingManager timingManager;
    +079    private final BukkitTask localeTask;
    +080    private final Logger logger;
    +081    public final Integer mcMinorVersion;
    +082    public final Integer mcPatchVersion;
    +083    protected Map<String, Command> knownCommands = new HashMap<>();
    +084    protected Map<String, BukkitRootCommand> registeredCommands = new HashMap<>();
    +085    protected BukkitCommandContexts contexts;
    +086    protected BukkitCommandCompletions completions;
    +087    MCTiming commandTiming;
    +088    protected BukkitLocales locales;
    +089    private boolean cantReadLocale = false;
    +090    protected boolean autoDetectFromClient = true;
    +091
    +092    @SuppressWarnings("JavaReflectionMemberAccess")
    +093    public BukkitCommandManager(Plugin plugin) {
    +094        this.plugin = plugin;
    +095        this.logger = Logger.getLogger(this.plugin.getName());
    +096        this.timingManager = TimingManager.of(plugin);
    +097        this.commandTiming = this.timingManager.of("Commands");
    +098        this.commandMap = hookCommandMap();
    +099        this.formatters.put(MessageType.ERROR, defaultFormatter = new BukkitMessageFormatter(ChatColor.RED, ChatColor.YELLOW, ChatColor.RED));
    +100        this.formatters.put(MessageType.SYNTAX, new BukkitMessageFormatter(ChatColor.YELLOW, ChatColor.GREEN, ChatColor.WHITE));
    +101        this.formatters.put(MessageType.INFO, new BukkitMessageFormatter(ChatColor.BLUE, ChatColor.DARK_GREEN, ChatColor.GREEN));
    +102        this.formatters.put(MessageType.HELP, new BukkitMessageFormatter(ChatColor.AQUA, ChatColor.GREEN, ChatColor.YELLOW));
    +103        Pattern versionPattern = Pattern.compile("\\(MC: (\\d)\\.(\\d+)\\.?(\\d+?)?\\)");
    +104        Matcher matcher = versionPattern.matcher(Bukkit.getVersion());
    +105        if (matcher.find()) {
    +106            this.mcMinorVersion = ACFUtil.parseInt(matcher.toMatchResult().group(2), 0);
    +107            this.mcPatchVersion = ACFUtil.parseInt(matcher.toMatchResult().group(3), 0);
    +108        } else {
    +109            this.mcMinorVersion = -1;
    +110            this.mcPatchVersion = -1;
    +111        }
    +112        Bukkit.getHelpMap().registerHelpTopicFactory(BukkitRootCommand.class, command -> {
    +113            if (hasUnstableAPI("help")) {
    +114                return new ACFBukkitHelpTopic(this, (BukkitRootCommand) command);
    +115            } else {
    +116                return new GenericCommandHelpTopic(command);
    +117            }
    +118        });
    +119
    +120        Bukkit.getPluginManager().registerEvents(new ACFBukkitListener(this, plugin), plugin);
    +121
    +122        getLocales(); // auto load locales
    +123        this.localeTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
    +124            if (this.cantReadLocale || !this.autoDetectFromClient) {
    +125                return;
    +126            }
    +127            Bukkit.getOnlinePlayers().forEach(this::readPlayerLocale);
    +128        }, 5, 5);
    +129
    +130        registerDependency(plugin.getClass(), plugin);
    +131        registerDependency(Logger.class, plugin.getLogger());
    +132        registerDependency(FileConfiguration.class, plugin.getConfig());
    +133        registerDependency(FileConfiguration.class, "config", plugin.getConfig());
    +134        registerDependency(Plugin.class, plugin);
    +135        registerDependency(JavaPlugin.class, plugin);
    +136        registerDependency(PluginManager.class, Bukkit.getPluginManager());
    +137        registerDependency(Server.class, Bukkit.getServer());
    +138        registerDependency(BukkitScheduler.class, Bukkit.getScheduler());
    +139        registerDependency(ScoreboardManager.class, Bukkit.getScoreboardManager());
    +140        registerDependency(ItemFactory.class, Bukkit.getItemFactory());
    +141    }
    +142
    +143    @NotNull
    +144    private CommandMap hookCommandMap() {
    +145        CommandMap commandMap = null;
    +146        try {
    +147            Server server = Bukkit.getServer();
    +148            Method getCommandMap = server.getClass().getDeclaredMethod("getCommandMap");
    +149            getCommandMap.setAccessible(true);
    +150            commandMap = (CommandMap) getCommandMap.invoke(server);
    +151            if (!SimpleCommandMap.class.isAssignableFrom(commandMap.getClass())) {
    +152                this.log(LogLevel.ERROR, "ERROR: CommandMap has been hijacked! Offending command map is located at: " + commandMap.getClass().getName());
    +153                this.log(LogLevel.ERROR, "We are going to try to hijack it back and resolve this, but you are now in dangerous territory.");
    +154                this.log(LogLevel.ERROR, "We can not guarantee things are going to work.");
    +155                Field cmField = server.getClass().getDeclaredField("commandMap");
    +156                commandMap = new ProxyCommandMap(this, commandMap);
    +157                cmField.set(server, commandMap);
    +158                this.log(LogLevel.INFO, "Injected Proxy Command Map... good luck...");
    +159            }
    +160            Field knownCommands = SimpleCommandMap.class.getDeclaredField("knownCommands");
    +161            knownCommands.setAccessible(true);
    +162            //noinspection unchecked
    +163            this.knownCommands = (Map<String, Command>) knownCommands.get(commandMap);
    +164        } catch (Exception e) {
    +165            this.log(LogLevel.ERROR, "Failed to get Command Map. ACF will not function.");
    +166            ACFUtil.sneaky(e);
    +167        }
    +168        return commandMap;
    +169    }
    +170
    +171    public Plugin getPlugin() {
    +172        return this.plugin;
    +173    }
    +174
    +175    @Override
    +176    public boolean isCommandIssuer(Class<?> type) {
    +177        return CommandSender.class.isAssignableFrom(type);
    +178    }
    +179
    +180    @Override
    +181    public synchronized CommandContexts<BukkitCommandExecutionContext> getCommandContexts() {
    +182        if (this.contexts == null) {
    +183            this.contexts = new BukkitCommandContexts(this);
    +184        }
    +185        return contexts;
    +186    }
    +187
    +188    @Override
    +189    public synchronized CommandCompletions<BukkitCommandCompletionContext> getCommandCompletions() {
    +190        if (this.completions == null) {
    +191            this.completions = new BukkitCommandCompletions(this);
    +192        }
    +193        return completions;
    +194    }
    +195
    +196
    +197    @Override
    +198    public BukkitLocales getLocales() {
    +199        if (this.locales == null) {
    +200            this.locales = new BukkitLocales(this);
    +201            this.locales.loadLanguages();
    +202        }
    +203        return locales;
    +204    }
    +205
    +206
    +207    @Override
    +208    public boolean hasRegisteredCommands() {
    +209        return !registeredCommands.isEmpty();
    +210    }
    +211
    +212    public void registerCommand(BaseCommand command, boolean force) {
    +213        final String plugin = this.plugin.getName().toLowerCase(Locale.ENGLISH);
    +214        command.onRegister(this);
    +215        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    +216            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
    +217            BukkitRootCommand bukkitCommand = (BukkitRootCommand) entry.getValue();
    +218            if (!bukkitCommand.isRegistered) {
    +219                Command oldCommand = commandMap.getCommand(commandName);
    +220                if (oldCommand instanceof PluginIdentifiableCommand && ((PluginIdentifiableCommand) oldCommand).getPlugin() == this.plugin) {
    +221                    knownCommands.remove(commandName);
    +222                    oldCommand.unregister(commandMap);
    +223                } else if (oldCommand != null && force) {
    +224                    knownCommands.remove(commandName);
    +225                    for (Map.Entry<String, Command> ce : knownCommands.entrySet()) {
    +226                        String key = ce.getKey();
    +227                        Command value = ce.getValue();
    +228                        if (key.contains(":") && oldCommand.equals(value)) {
    +229                            String[] split = ACFPatterns.COLON.split(key, 2);
    +230                            if (split.length > 1) {
    +231                                oldCommand.unregister(commandMap);
    +232                                oldCommand.setLabel(split[0] + ":" + command.getName());
    +233                                oldCommand.register(commandMap);
    +234                            }
    +235                        }
    +236                    }
    +237                }
    +238                commandMap.register(commandName, plugin, bukkitCommand);
    +239            }
    +240            bukkitCommand.isRegistered = true;
    +241            registeredCommands.put(commandName, bukkitCommand);
    +242        }
    +243    }
    +244
    +245    @Override
    +246    public void registerCommand(BaseCommand command) {
    +247        registerCommand(command, false);
    +248    }
    +249
    +250    public void unregisterCommand(BaseCommand command) {
    +251        for (RootCommand rootcommand : command.registeredCommands.values()) {
    +252            BukkitRootCommand bukkitCommand = (BukkitRootCommand) rootcommand;
    +253            bukkitCommand.getSubCommands().values().removeAll(command.subCommands.values());
    +254            if (bukkitCommand.isRegistered && bukkitCommand.getSubCommands().isEmpty()) {
    +255                unregisterCommand(bukkitCommand);
    +256                bukkitCommand.isRegistered = false;
    +257            }
    +258        }
    +259    }
    +260
    +261    /**
    +262     * @param command
    +263     * @deprecated Use unregisterCommand(BaseCommand) - this will be visibility reduced later.
    +264     */
    +265    @Deprecated
    +266    public void unregisterCommand(BukkitRootCommand command) {
    +267        final String plugin = this.plugin.getName().toLowerCase(Locale.ENGLISH);
    +268        command.unregister(commandMap);
    +269        String key = command.getName();
    +270        Command registered = knownCommands.get(key);
    +271        if (command.equals(registered)) {
    +272            knownCommands.remove(key);
    +273        }
    +274        knownCommands.remove(plugin + ":" + key);
    +275        registeredCommands.remove(key);
    +276    }
    +277
    +278    public void unregisterCommands() {
    +279        for (String key : new HashSet<>(registeredCommands.keySet())) {
    +280            unregisterCommand(registeredCommands.get(key));
    +281        }
    +282    }
    +283
    +284
    +285    private Field getEntityField(Player player) throws NoSuchFieldException {
    +286        Class cls = player.getClass();
    +287        while (cls != Object.class) {
    +288            if (cls.getName().endsWith("CraftEntity")) {
    +289                Field field = cls.getDeclaredField("entity");
    +290                field.setAccessible(true);
    +291                return field;
    +292            }
    +293            cls = cls.getSuperclass();
    +294        }
    +295        return null;
    +296    }
    +297
    +298    public Locale setPlayerLocale(Player player, Locale locale) {
    +299        return this.setIssuerLocale(player, locale);
    +300    }
    +301
    +302    void readPlayerLocale(Player player) {
    +303        if (!player.isOnline() || cantReadLocale) {
    +304            return;
    +305        }
    +306        try {
    +307            Field entityField = getEntityField(player);
    +308            if (entityField == null) {
    +309                return;
    +310            }
    +311            Object nmsPlayer = entityField.get(player);
    +312            if (nmsPlayer != null) {
    +313                Field localeField = nmsPlayer.getClass().getDeclaredField("locale");
    +314                localeField.setAccessible(true);
    +315                Object localeString = localeField.get(nmsPlayer);
    +316                if (localeString instanceof String) {
    +317                    String[] split = ACFPatterns.UNDERSCORE.split((String) localeString);
    +318                    Locale locale = split.length > 1 ? new Locale(split[0], split[1]) : new Locale(split[0]);
    +319                    Locale prev = issuersLocale.put(player.getUniqueId(), locale);
    +320                    if (!Objects.equals(locale, prev)) {
    +321                        this.notifyLocaleChange(getCommandIssuer(player), prev, locale);
    +322                    }
    +323                }
    +324            }
    +325        } catch (Exception e) {
    +326            cantReadLocale = true;
    +327            this.localeTask.cancel();
    +328            this.log(LogLevel.INFO, "Can't read players locale, you will be unable to automatically detect players language. Only Bukkit 1.7+ is supported for this.", e);
    +329        }
    +330    }
    +331
    +332    public TimingManager getTimings() {
    +333        return timingManager;
    +334    }
    +335
    +336    @Override
    +337    public RootCommand createRootCommand(String cmd) {
    +338        return new BukkitRootCommand(this, cmd);
    +339    }
    +340
    +341    @Override
    +342    public Collection<RootCommand> getRegisteredRootCommands() {
    +343        return Collections.unmodifiableCollection(registeredCommands.values());
    +344    }
    +345
    +346    @Override
    +347    public BukkitCommandIssuer getCommandIssuer(Object issuer) {
    +348        if (!(issuer instanceof CommandSender)) {
    +349            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
    +350        }
    +351        return new BukkitCommandIssuer(this, (CommandSender) issuer);
    +352    }
    +353
    +354    @Override
    +355    public BukkitCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
    +356        return new BukkitCommandExecutionContext(command, parameter, (BukkitCommandIssuer) sender, args, i, passedArgs);
    +357    }
    +358
    +359    @Override
    +360    public BukkitCommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
    +361        return new BukkitCommandCompletionContext(command, (BukkitCommandIssuer) sender, input, config, args);
    +362    }
    +363
    +364    @Override
    +365    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
    +366        return new BukkitRegisteredCommand(command, cmdName, method, prefSubCommand);
    +367    }
    +368
    +369    @Override
    +370    public BukkitConditionContext createConditionContext(CommandIssuer issuer, String config) {
    +371        return new BukkitConditionContext((BukkitCommandIssuer) issuer, config);
    +372    }
    +373
    +374
    +375    @Override
    +376    public void log(LogLevel level, String message, Throwable throwable) {
    +377        Level logLevel = level == LogLevel.INFO ? Level.INFO : Level.SEVERE;
    +378        logger.log(logLevel, LogLevel.LOG_PREFIX + message);
    +379        if (throwable != null) {
    +380            for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    +381                logger.log(logLevel, LogLevel.LOG_PREFIX + line);
    +382            }
    +383        }
    +384    }
    +385
    +386    public boolean usePerIssuerLocale(boolean usePerIssuerLocale, boolean autoDetectFromClient) {
    +387        boolean old = this.usePerIssuerLocale;
    +388        this.usePerIssuerLocale = usePerIssuerLocale;
    +389        this.autoDetectFromClient = autoDetectFromClient;
    +390        return old;
    +391    }
    +392
    +393    @Override
    +394    public String getCommandPrefix(CommandIssuer issuer) {
    +395        return issuer.isPlayer() ? "/" : "";
    +396    }
    +397
    +398    @Override
    +399    protected boolean handleUncaughtException(BaseCommand scope, RegisteredCommand registeredCommand, CommandIssuer sender, List<String> args, Throwable t) {
    +400        if (t instanceof CommandException && t.getCause() != null && t.getMessage().startsWith("Unhandled exception")) {
    +401            t = t.getCause();
    +402        }
    +403        return super.handleUncaughtException(scope, registeredCommand, sender, args, t);
    +404    }
    +405}
     
     
     
    @@ -473,5 +474,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitConditionContext.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitConditionContext.html index 8097d447..c64d5e35 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitConditionContext.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitConditionContext.html @@ -1,52 +1,53 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.bukkit.command.CommandSender;
    -027import org.bukkit.entity.Player;
    -028
    -029public class BukkitConditionContext extends ConditionContext<BukkitCommandIssuer> {
    -030    BukkitConditionContext(BukkitCommandIssuer issuer, String config) {
    -031        super(issuer, config);
    -032    }
    -033
    -034    public CommandSender getSender() {
    -035        return getIssuer().getIssuer();
    -036    }
    -037
    -038    public Player getPlayer() {
    -039        return getIssuer().getPlayer();
    -040    }
    -041}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.bukkit.command.CommandSender;
    +027import org.bukkit.entity.Player;
    +028
    +029public class BukkitConditionContext extends ConditionContext<BukkitCommandIssuer> {
    +030    BukkitConditionContext(BukkitCommandIssuer issuer, String config) {
    +031        super(issuer, config);
    +032    }
    +033
    +034    public CommandSender getSender() {
    +035        return getIssuer().getIssuer();
    +036    }
    +037
    +038    public Player getPlayer() {
    +039        return getIssuer().getPlayer();
    +040    }
    +041}
     
     
     
    @@ -109,5 +110,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitLocales.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitLocales.html index 3a249b13..15ce490c 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitLocales.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitLocales.html @@ -1,116 +1,117 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.locales.MessageKey;
    -027import org.bukkit.configuration.ConfigurationSection;
    -028import org.bukkit.configuration.InvalidConfigurationException;
    -029import org.bukkit.configuration.file.FileConfiguration;
    -030import org.bukkit.configuration.file.YamlConfiguration;
    -031
    -032import java.io.File;
    -033import java.io.IOException;
    -034import java.util.Locale;
    -035
    -036public class BukkitLocales extends Locales {
    -037    private final BukkitCommandManager manager;
    -038
    -039    public BukkitLocales(BukkitCommandManager manager) {
    -040        super(manager);
    -041        this.manager = manager;
    -042        this.addBundleClassLoader(this.manager.getPlugin().getClass().getClassLoader());
    -043    }
    -044
    -045    @Override
    -046    public void loadLanguages() {
    -047        super.loadLanguages();
    -048        String pluginName = "acf-" + manager.plugin.getDescription().getName();
    -049        addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
    -050    }
    -051
    -052    /**
    -053     * Loads the given file
    -054     * @param file
    -055     * @param locale
    -056     * @return If any language keys were added
    -057     * @throws IOException
    -058     * @throws InvalidConfigurationException
    -059     */
    -060    public boolean loadYamlLanguageFile(File file, Locale locale) throws IOException, InvalidConfigurationException {
    -061        YamlConfiguration yamlConfiguration = new YamlConfiguration();
    -062        yamlConfiguration.load(file);
    -063        return loadLanguage(yamlConfiguration, locale);
    -064    }
    -065
    -066    /**
    -067     * Loads a file out of the plugins data folder by the given name
    -068     * @param file
    -069     * @param locale
    -070     * @return If any language keys were added
    -071     * @throws IOException
    -072     * @throws InvalidConfigurationException
    -073     */
    -074    public boolean loadYamlLanguageFile(String file, Locale locale) throws IOException, InvalidConfigurationException {
    -075        YamlConfiguration yamlConfiguration = new YamlConfiguration();
    -076        yamlConfiguration.load(new File(this.manager.plugin.getDataFolder(), file));
    -077        return loadLanguage(yamlConfiguration, locale);
    -078    }
    -079
    -080    /**
    -081     * Loads every message from the Configuration object. Any nested values will be treated as namespace
    -082     * so acf-core:\n\tfoo: bar will be acf-core.foo = bar
    -083     * @param config
    -084     * @param locale
    -085     * @return If any language keys were added
    -086     */
    -087    public boolean loadLanguage(FileConfiguration config, Locale locale) {
    -088        boolean loaded = false;
    -089        for (String parentKey : config.getKeys(false)) {
    -090            ConfigurationSection inner = config.getConfigurationSection(parentKey);
    -091            if (inner == null) {
    -092                continue;
    -093            }
    -094            for (String key : inner.getKeys(false)) {
    -095                String value = inner.getString(key);
    -096                if (value != null && !value.isEmpty()) {
    -097                    addMessage(locale, MessageKey.of(parentKey + "." + key), value);
    -098                    loaded = true;
    -099                }
    -100            }
    -101        }
    -102
    -103        return loaded;
    -104    }
    -105}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.locales.MessageKey;
    +027import org.bukkit.configuration.ConfigurationSection;
    +028import org.bukkit.configuration.InvalidConfigurationException;
    +029import org.bukkit.configuration.file.FileConfiguration;
    +030import org.bukkit.configuration.file.YamlConfiguration;
    +031
    +032import java.io.File;
    +033import java.io.IOException;
    +034import java.util.Locale;
    +035
    +036public class BukkitLocales extends Locales {
    +037    private final BukkitCommandManager manager;
    +038
    +039    public BukkitLocales(BukkitCommandManager manager) {
    +040        super(manager);
    +041        this.manager = manager;
    +042        this.addBundleClassLoader(this.manager.getPlugin().getClass().getClassLoader());
    +043    }
    +044
    +045    @Override
    +046    public void loadLanguages() {
    +047        super.loadLanguages();
    +048        String pluginName = "acf-" + manager.plugin.getDescription().getName();
    +049        addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase(Locale.ENGLISH));
    +050    }
    +051
    +052    /**
    +053     * Loads the given file
    +054     * @param file
    +055     * @param locale
    +056     * @return If any language keys were added
    +057     * @throws IOException
    +058     * @throws InvalidConfigurationException
    +059     */
    +060    public boolean loadYamlLanguageFile(File file, Locale locale) throws IOException, InvalidConfigurationException {
    +061        YamlConfiguration yamlConfiguration = new YamlConfiguration();
    +062        yamlConfiguration.load(file);
    +063        return loadLanguage(yamlConfiguration, locale);
    +064    }
    +065
    +066    /**
    +067     * Loads a file out of the plugins data folder by the given name
    +068     * @param file
    +069     * @param locale
    +070     * @return If any language keys were added
    +071     * @throws IOException
    +072     * @throws InvalidConfigurationException
    +073     */
    +074    public boolean loadYamlLanguageFile(String file, Locale locale) throws IOException, InvalidConfigurationException {
    +075        YamlConfiguration yamlConfiguration = new YamlConfiguration();
    +076        yamlConfiguration.load(new File(this.manager.plugin.getDataFolder(), file));
    +077        return loadLanguage(yamlConfiguration, locale);
    +078    }
    +079
    +080    /**
    +081     * Loads every message from the Configuration object. Any nested values will be treated as namespace
    +082     * so acf-core:\n\tfoo: bar will be acf-core.foo = bar
    +083     * @param config
    +084     * @param locale
    +085     * @return If any language keys were added
    +086     */
    +087    public boolean loadLanguage(FileConfiguration config, Locale locale) {
    +088        boolean loaded = false;
    +089        for (String parentKey : config.getKeys(false)) {
    +090            ConfigurationSection inner = config.getConfigurationSection(parentKey);
    +091            if (inner == null) {
    +092                continue;
    +093            }
    +094            for (String key : inner.getKeys(false)) {
    +095                String value = inner.getString(key);
    +096                if (value != null && !value.isEmpty()) {
    +097                    addMessage(locale, MessageKey.of(parentKey + "." + key), value);
    +098                    loaded = true;
    +099                }
    +100            }
    +101        }
    +102
    +103        return loaded;
    +104    }
    +105}
     
     
     
    @@ -173,5 +174,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitMessageFormatter.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitMessageFormatter.html index 01e9b035..620c56f8 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitMessageFormatter.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitMessageFormatter.html @@ -1,49 +1,50 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.bukkit.ChatColor;
    -027
    -028public class BukkitMessageFormatter extends MessageFormatter<ChatColor> {
    -029
    -030    public BukkitMessageFormatter(ChatColor... colors) {
    -031        super(colors);
    -032    }
    -033
    -034    @Override
    -035    String format(ChatColor color, String message) {
    -036        return color + message;
    -037    }
    -038}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.bukkit.ChatColor;
    +027
    +028public class BukkitMessageFormatter extends MessageFormatter<ChatColor> {
    +029
    +030    public BukkitMessageFormatter(ChatColor... colors) {
    +031        super(colors);
    +032    }
    +033
    +034    @Override
    +035    String format(ChatColor color, String message) {
    +036        return color + message;
    +037    }
    +038}
     
     
     
    @@ -106,5 +107,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitRegisteredCommand.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitRegisteredCommand.html index aaeaecb9..45a43605 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitRegisteredCommand.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitRegisteredCommand.html @@ -1,61 +1,62 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.timings.lib.MCTiming;
    -027
    -028import java.lang.reflect.Method;
    -029
    -030public class BukkitRegisteredCommand extends RegisteredCommand<BukkitCommandExecutionContext> {
    -031    private final MCTiming timing;
    -032    BukkitRegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) {
    -033        super(scope, command, method, prefSubCommand);
    -034        BukkitCommandManager manager = (BukkitCommandManager) scope.manager;
    -035        this.timing = manager.getTimings().of("Command: " + this.command, manager.commandTiming);
    -036    }
    -037
    -038
    -039    @Override
    -040    public void preCommand() {
    -041        timing.startTiming();
    -042        super.preCommand();
    -043    }
    -044
    -045    @Override
    -046    public void postCommand() {
    -047        super.postCommand();
    -048        timing.stopTiming();
    -049    }
    -050}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.timings.lib.MCTiming;
    +027
    +028import java.lang.reflect.Method;
    +029
    +030public class BukkitRegisteredCommand extends RegisteredCommand<BukkitCommandExecutionContext> {
    +031    private final MCTiming timing;
    +032    BukkitRegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) {
    +033        super(scope, command, method, prefSubCommand);
    +034        BukkitCommandManager manager = (BukkitCommandManager) scope.manager;
    +035        this.timing = manager.getTimings().of("Command: " + this.command, manager.commandTiming);
    +036    }
    +037
    +038
    +039    @Override
    +040    public void preCommand() {
    +041        timing.startTiming();
    +042        super.preCommand();
    +043    }
    +044
    +045    @Override
    +046    public void postCommand() {
    +047        super.postCommand();
    +048        timing.stopTiming();
    +049    }
    +050}
     
     
     
    @@ -118,5 +119,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitRootCommand.html b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitRootCommand.html index 2706f298..09e81228 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/BukkitRootCommand.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/BukkitRootCommand.html @@ -1,127 +1,128 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import com.google.common.collect.HashMultimap;
    -027import com.google.common.collect.SetMultimap;
    -028import org.bukkit.command.Command;
    -029import org.bukkit.command.CommandSender;
    -030
    -031import java.util.ArrayList;
    -032import java.util.List;
    -033
    -034public class BukkitRootCommand extends Command implements RootCommand {
    -035
    -036    private final BukkitCommandManager manager;
    -037    private final String name;
    -038    private BaseCommand defCommand;
    -039    private SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
    -040    private List<BaseCommand> children = new ArrayList<>();
    -041    boolean isRegistered = false;
    -042
    -043    BukkitRootCommand(BukkitCommandManager manager, String name) {
    -044        super(name);
    -045        this.manager = manager;
    -046        this.name = name;
    -047    }
    -048
    -049    @Override
    -050    public String getDescription() {
    -051        RegisteredCommand command = getDefaultRegisteredCommand();
    -052
    -053        if (command != null && !command.getHelpText().isEmpty()) {
    -054            return command.getHelpText();
    -055        }
    -056        if (command != null && command.scope.description != null) {
    -057            return command.scope.description;
    -058        }
    -059        if (defCommand.description != null) {
    -060            return defCommand.description;
    -061        }
    -062        return super.getDescription();
    -063    }
    -064
    -065    @Override
    -066    public String getCommandName() {
    -067        return name;
    -068    }
    -069
    -070    @Override
    -071    public List<String> tabComplete(CommandSender sender, String commandLabel, String[] args) throws IllegalArgumentException {
    -072        if (commandLabel.contains(":")) commandLabel = ACFPatterns.COLON.split(commandLabel, 2)[1];
    -073        return getTabCompletions(manager.getCommandIssuer(sender), commandLabel, args);
    -074    }
    -075
    -076    @Override
    -077    public boolean execute(CommandSender sender, String commandLabel, String[] args) {
    -078        if (commandLabel.contains(":")) commandLabel = ACFPatterns.COLON.split(commandLabel, 2)[1];
    -079        execute(manager.getCommandIssuer(sender), commandLabel, args);
    -080        return true;
    -081    }
    -082
    -083    @Override
    -084    public boolean testPermissionSilent(CommandSender target) {
    -085        return hasAnyPermission(manager.getCommandIssuer(target));
    -086    }
    -087
    -088    public void addChild(BaseCommand command) {
    -089        if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) {
    -090            this.defCommand = command;
    -091        }
    -092        addChildShared(this.children, this.subCommands, command);
    -093        setPermission(getUniquePermission());
    -094    }
    -095
    -096    @Override
    -097    public CommandManager getManager() {
    -098        return manager;
    -099    }
    -100
    -101    @Override
    -102    public SetMultimap<String, RegisteredCommand> getSubCommands() {
    -103        return this.subCommands;
    -104    }
    -105
    -106    @Override
    -107    public List<BaseCommand> getChildren() {
    -108        return children;
    -109    }
    -110
    -111    @Override
    -112    public BaseCommand getDefCommand() {
    -113        return defCommand;
    -114    }
    -115
    -116}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import com.google.common.collect.HashMultimap;
    +027import com.google.common.collect.SetMultimap;
    +028import org.bukkit.command.Command;
    +029import org.bukkit.command.CommandSender;
    +030
    +031import java.util.ArrayList;
    +032import java.util.List;
    +033
    +034public class BukkitRootCommand extends Command implements RootCommand {
    +035
    +036    private final BukkitCommandManager manager;
    +037    private final String name;
    +038    private BaseCommand defCommand;
    +039    private SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
    +040    private List<BaseCommand> children = new ArrayList<>();
    +041    boolean isRegistered = false;
    +042
    +043    BukkitRootCommand(BukkitCommandManager manager, String name) {
    +044        super(name);
    +045        this.manager = manager;
    +046        this.name = name;
    +047    }
    +048
    +049    @Override
    +050    public String getDescription() {
    +051        RegisteredCommand command = getDefaultRegisteredCommand();
    +052
    +053        if (command != null && !command.getHelpText().isEmpty()) {
    +054            return command.getHelpText();
    +055        }
    +056        if (command != null && command.scope.description != null) {
    +057            return command.scope.description;
    +058        }
    +059        if (defCommand.description != null) {
    +060            return defCommand.description;
    +061        }
    +062        return super.getDescription();
    +063    }
    +064
    +065    @Override
    +066    public String getCommandName() {
    +067        return name;
    +068    }
    +069
    +070    @Override
    +071    public List<String> tabComplete(CommandSender sender, String commandLabel, String[] args) throws IllegalArgumentException {
    +072        if (commandLabel.contains(":")) commandLabel = ACFPatterns.COLON.split(commandLabel, 2)[1];
    +073        return getTabCompletions(manager.getCommandIssuer(sender), commandLabel, args);
    +074    }
    +075
    +076    @Override
    +077    public boolean execute(CommandSender sender, String commandLabel, String[] args) {
    +078        if (commandLabel.contains(":")) commandLabel = ACFPatterns.COLON.split(commandLabel, 2)[1];
    +079        execute(manager.getCommandIssuer(sender), commandLabel, args);
    +080        return true;
    +081    }
    +082
    +083    @Override
    +084    public boolean testPermissionSilent(CommandSender target) {
    +085        return hasAnyPermission(manager.getCommandIssuer(target));
    +086    }
    +087
    +088    public void addChild(BaseCommand command) {
    +089        if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) {
    +090            this.defCommand = command;
    +091        }
    +092        addChildShared(this.children, this.subCommands, command);
    +093        setPermission(getUniquePermission());
    +094    }
    +095
    +096    @Override
    +097    public CommandManager getManager() {
    +098        return manager;
    +099    }
    +100
    +101    @Override
    +102    public SetMultimap<String, RegisteredCommand> getSubCommands() {
    +103        return this.subCommands;
    +104    }
    +105
    +106    @Override
    +107    public List<BaseCommand> getChildren() {
    +108        return children;
    +109    }
    +110
    +111    @Override
    +112    public BaseCommand getDefCommand() {
    +113        return defCommand;
    +114    }
    +115
    +116}
     
     
     
    @@ -184,5 +185,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/MinecraftMessageKeys.html b/docs/acf-bukkit/src-html/co/aikar/commands/MinecraftMessageKeys.html index 0ee6b52d..4c99517c 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/MinecraftMessageKeys.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/MinecraftMessageKeys.html @@ -1,58 +1,61 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.locales.MessageKey;
    -027import co.aikar.locales.MessageKeyProvider;
    -028
    -029public enum MinecraftMessageKeys implements MessageKeyProvider {
    -030    INVALID_WORLD,
    -031    YOU_MUST_BE_HOLDING_ITEM,
    -032    PLAYER_IS_VANISHED_CONFIRM,
    -033    USERNAME_TOO_SHORT,
    -034    IS_NOT_A_VALID_NAME,
    -035    MULTIPLE_PLAYERS_MATCH,
    -036    NO_PLAYER_FOUND_SERVER,
    -037    NO_PLAYER_FOUND_OFFLINE,
    -038    NO_PLAYER_FOUND,
    -039    LOCATION_PLEASE_SPECIFY_WORLD,
    -040    LOCATION_PLEASE_SPECIFY_XYZ,
    -041    LOCATION_CONSOLE_NOT_RELATIVE;
    -042
    -043    private final MessageKey key = MessageKey.of("acf-minecraft." + this.name().toLowerCase());
    -044    public MessageKey getMessageKey() {
    -045        return key;
    -046    }
    -047}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.locales.MessageKey;
    +027import co.aikar.locales.MessageKeyProvider;
    +028
    +029import java.util.Locale;
    +030
    +031public enum MinecraftMessageKeys implements MessageKeyProvider {
    +032    INVALID_WORLD,
    +033    YOU_MUST_BE_HOLDING_ITEM,
    +034    PLAYER_IS_VANISHED_CONFIRM,
    +035    USERNAME_TOO_SHORT,
    +036    IS_NOT_A_VALID_NAME,
    +037    MULTIPLE_PLAYERS_MATCH,
    +038    NO_PLAYER_FOUND_SERVER,
    +039    NO_PLAYER_FOUND_OFFLINE,
    +040    NO_PLAYER_FOUND,
    +041    LOCATION_PLEASE_SPECIFY_WORLD,
    +042    LOCATION_PLEASE_SPECIFY_XYZ,
    +043    LOCATION_CONSOLE_NOT_RELATIVE;
    +044
    +045    private final MessageKey key = MessageKey.of("acf-minecraft." + this.name().toLowerCase(Locale.ENGLISH));
    +046    public MessageKey getMessageKey() {
    +047        return key;
    +048    }
    +049}
     
     
     
    @@ -115,5 +118,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/bukkit/contexts/OnlinePlayer.html b/docs/acf-bukkit/src-html/co/aikar/commands/bukkit/contexts/OnlinePlayer.html index 84d942cc..c9b9ac6d 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/bukkit/contexts/OnlinePlayer.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/bukkit/contexts/OnlinePlayer.html @@ -1,69 +1,70 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands.bukkit.contexts;
    -025
    -026import org.bukkit.entity.Player;
    -027
    -028import java.util.Objects;
    -029
    -030public class OnlinePlayer {
    -031    public final Player player;
    -032
    -033    public OnlinePlayer(Player player) {
    -034        this.player = player;
    -035    }
    -036
    -037    public Player getPlayer() {
    -038        return this.player;
    -039    }
    -040
    -041    @Override
    -042    public boolean equals(Object o) {
    -043        if (this == o) return true;
    -044        if (o == null || getClass() != o.getClass()) return false;
    -045        OnlinePlayer that = (OnlinePlayer) o;
    -046        return Objects.equals(player, that.player);
    -047    }
    -048
    -049    @Override
    -050    public int hashCode() {
    -051        return Objects.hash(player);
    -052    }
    -053
    -054    @Override
    -055    public String toString() {
    -056        return "OnlinePlayer{player=" + player + '}';
    -057    }
    -058}
    +
    001/*
    +002 * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands.bukkit.contexts;
    +025
    +026import org.bukkit.entity.Player;
    +027
    +028import java.util.Objects;
    +029
    +030public class OnlinePlayer {
    +031    public final Player player;
    +032
    +033    public OnlinePlayer(Player player) {
    +034        this.player = player;
    +035    }
    +036
    +037    public Player getPlayer() {
    +038        return this.player;
    +039    }
    +040
    +041    @Override
    +042    public boolean equals(Object o) {
    +043        if (this == o) return true;
    +044        if (o == null || getClass() != o.getClass()) return false;
    +045        OnlinePlayer that = (OnlinePlayer) o;
    +046        return Objects.equals(player, that.player);
    +047    }
    +048
    +049    @Override
    +050    public int hashCode() {
    +051        return Objects.hash(player);
    +052    }
    +053
    +054    @Override
    +055    public String toString() {
    +056        return "OnlinePlayer{player=" + player + '}';
    +057    }
    +058}
     
     
     
    @@ -126,5 +127,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/src-html/co/aikar/commands/contexts/OnlinePlayer.html b/docs/acf-bukkit/src-html/co/aikar/commands/contexts/OnlinePlayer.html index eb8f98a1..430419f1 100644 --- a/docs/acf-bukkit/src-html/co/aikar/commands/contexts/OnlinePlayer.html +++ b/docs/acf-bukkit/src-html/co/aikar/commands/contexts/OnlinePlayer.html @@ -1,47 +1,48 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands.contexts;
    -025
    -026import org.bukkit.entity.Player;
    -027
    -028/**
    -029 * @deprecated Use {@link co.aikar.commands.bukkit.contexts.OnlinePlayer instead}
    -030 */
    -031@Deprecated
    -032public class OnlinePlayer extends co.aikar.commands.bukkit.contexts.OnlinePlayer {
    -033    public OnlinePlayer(Player player) {
    -034        super(player);
    -035    }
    -036}
    +
    001/*
    +002 * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands.contexts;
    +025
    +026import org.bukkit.entity.Player;
    +027
    +028/**
    +029 * @deprecated Use {@link co.aikar.commands.bukkit.contexts.OnlinePlayer instead}
    +030 */
    +031@Deprecated
    +032public class OnlinePlayer extends co.aikar.commands.bukkit.contexts.OnlinePlayer {
    +033    public OnlinePlayer(Player player) {
    +034        super(player);
    +035    }
    +036}
     
     
     
    @@ -104,5 +105,6 @@
     
     
    +
    diff --git a/docs/acf-bukkit/stylesheet.css b/docs/acf-bukkit/stylesheet.css index 98055b22..fa246765 100644 --- a/docs/acf-bukkit/stylesheet.css +++ b/docs/acf-bukkit/stylesheet.css @@ -1,35 +1,51 @@ -/* Javadoc style sheet */ -/* -Overall document style -*/ +/* + * Javadoc style sheet + */ @import url('resources/fonts/dejavu.css'); +/* + * Styles for individual HTML elements. + * + * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular + * HTML element throughout the page. + */ + body { background-color:#ffffff; color:#353833; font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; font-size:14px; margin:0; + padding:0; + height:100%; + width:100%; +} +iframe { + margin:0; + padding:0; + height:100%; + width:100%; + overflow-y:scroll; + border:none; } a:link, a:visited { text-decoration:none; color:#4A6782; } -a:hover, a:focus { +a[href]:hover, a[href]:focus { text-decoration:none; color:#bb7a2a; } -a:active { - text-decoration:none; - color:#4A6782; -} a[name] { color:#353833; } -a[name]:hover { - text-decoration:none; - color:#353833; +a[name]:before, a[name]:target, a[id]:before, a[id]:target { + content:""; + display:inline-block; + position:relative; + padding-top:129px; + margin-top:-129px; } pre { font-family:'DejaVu Sans Mono', monospace; @@ -78,9 +94,16 @@ table tr td dt code { sup { font-size:8px; } + /* -Document title and Copyright styles -*/ + * Styles for HTML generated by javadoc. + * + * These are style classes that are used by the standard doclet to generate HTML documentation. + */ + +/* + * Styles for document title and copyright. + */ .clear { clear:both; height:0px; @@ -111,8 +134,8 @@ Document title and Copyright styles font-weight:bold; } /* -Navigation bar styles -*/ + * Styles for navigation bar. + */ .bar { background-color:#4D7A97; color:#FFFFFF; @@ -121,6 +144,15 @@ Navigation bar styles font-size:11px; margin:0; } +.navPadding { + padding-top: 107px; +} +.fixedNav { + position:fixed; + width:100%; + z-index:999; + background-color:#ffffff; +} .topNav { background-color:#4D7A97; color:#FFFFFF; @@ -170,7 +202,22 @@ ul.navList li{ padding: 5px 6px; text-transform:uppercase; } -ul.subNavList li{ +ul.navListSearch { + float:right; + margin:0 0 0 0; + padding:0; +} +ul.navListSearch li { + list-style:none; + float:right; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch li label { + position:relative; + right:-16px; +} +ul.subNavList li { list-style:none; float:left; } @@ -196,21 +243,29 @@ ul.subNavList li{ overflow:hidden; } /* -Page header and footer styles -*/ + * Styles for page header and footer. + */ .header, .footer { clear:both; margin:0 20px; padding:5px 0 0 0; } -.indexHeader { - margin:10px; +.indexNav { position:relative; + font-size:12px; + background-color:#dee3e9; } -.indexHeader span{ - margin-right:15px; +.indexNav ul { + margin-top:0; + padding:5px; } -.indexHeader h1 { +.indexNav ul li { + display:inline; + list-style-type:none; + padding-right:10px; + text-transform:uppercase; +} +.indexNav h1 { font-size:13px; } .title { @@ -232,8 +287,8 @@ Page header and footer styles font-size:13px; } /* -Heading styles -*/ + * Styles for headings. + */ div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { background-color:#dee3e9; border:1px solid #d0d9e0; @@ -254,9 +309,10 @@ ul.blockList li.blockList h2 { padding:0px 0 20px 0; } /* -Page layout container styles -*/ -.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + * Styles for page layout containers. + */ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer, +.allClassesContainer, .allPackagesContainer { clear:both; padding:10px 20px; position:relative; @@ -287,7 +343,7 @@ Page layout container styles .contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { margin:5px 0 10px 0px; font-size:14px; - font-family:'DejaVu Sans Mono',monospace; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } .serializedFormContainer dl.nameValue dt { margin-left:1px; @@ -301,8 +357,11 @@ Page layout container styles display:inline; } /* -List styles -*/ + * Styles for lists. + */ +li.circle { + list-style:circle; +} ul.horizontal li { display:inline; font-size:0.9em; @@ -355,19 +414,22 @@ table tr td dl, table tr td dl dt, table tr td dl dd { margin-bottom:1px; } /* -Table styles -*/ -.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + * Styles for tables. + */ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary, +.requiresSummary, .packagesSummary, .providesSummary, .usesSummary { width:100%; + border-spacing:0; border-left:1px solid #EEE; border-right:1px solid #EEE; border-bottom:1px solid #EEE; } -.overviewSummary, .memberSummary { +.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary { padding:0px; } .overviewSummary caption, .memberSummary caption, .typeSummary caption, -.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption, +.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption { position:relative; text-align:left; background-repeat:no-repeat; @@ -382,17 +444,31 @@ Table styles white-space:pre; } .overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, -.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.constantsSummary caption a:link, .deprecatedSummary caption a:link, +.requiresSummary caption a:link, .packagesSummary caption a:link, .providesSummary caption a:link, +.usesSummary caption a:link, .overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, -.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.requiresSummary caption a:hover, .packagesSummary caption a:hover, .providesSummary caption a:hover, +.usesSummary caption a:hover, .overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, -.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.constantsSummary caption a:active, .deprecatedSummary caption a:active, +.requiresSummary caption a:active, .packagesSummary caption a:active, .providesSummary caption a:active, +.usesSummary caption a:active, .overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, -.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { +.constantsSummary caption a:visited, .deprecatedSummary caption a:visited, +.requiresSummary caption a:visited, .packagesSummary caption a:visited, .providesSummary caption a:visited, +.usesSummary caption a:visited { color:#FFFFFF; } +.useSummary caption a:link, .useSummary caption a:hover, .useSummary caption a:active, +.useSummary caption a:visited { + color:#1f389c; +} .overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, -.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span, +.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span, +.usesSummary caption span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -404,7 +480,8 @@ Table styles border: none; height:16px; } -.memberSummary caption span.activeTableTab span { +.memberSummary caption span.activeTableTab span, .packagesSummary caption span.activeTableTab span, +.overviewSummary caption span.activeTableTab span, .typeSummary caption span.activeTableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -415,7 +492,8 @@ Table styles background-color:#F8981D; height:16px; } -.memberSummary caption span.tableTab span { +.memberSummary caption span.tableTab span, .packagesSummary caption span.tableTab span, +.overviewSummary caption span.tableTab span, .typeSummary caption span.tableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -426,7 +504,10 @@ Table styles background-color:#4D7A97; height:16px; } -.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab, +.packagesSummary caption span.tableTab, .packagesSummary caption span.activeTableTab, +.overviewSummary caption span.tableTab, .overviewSummary caption span.activeTableTab, +.typeSummary caption span.tableTab, .typeSummary caption span.activeTableTab { padding-top:0px; padding-left:0px; padding-right:0px; @@ -435,14 +516,16 @@ Table styles display:inline; } .overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, -.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd, +.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd { display:none; width:5px; position:relative; float:left; background-color:#F8981D; } -.memberSummary .activeTableTab .tabEnd { +.memberSummary .activeTableTab .tabEnd, .packagesSummary .activeTableTab .tabEnd, +.overviewSummary .activeTableTab .tabEnd, .typeSummary .activeTableTab .tabEnd { display:none; width:5px; margin-right:3px; @@ -450,66 +533,88 @@ Table styles float:left; background-color:#F8981D; } -.memberSummary .tableTab .tabEnd { +.memberSummary .tableTab .tabEnd, .packagesSummary .tableTab .tabEnd, +.overviewSummary .tableTab .tabEnd, .typeSummary .tableTab .tabEnd { display:none; width:5px; margin-right:3px; position:relative; background-color:#4D7A97; float:left; - +} +.rowColor th, .altColor th { + font-weight:normal; } .overviewSummary td, .memberSummary td, .typeSummary td, -.useSummary td, .constantsSummary td, .deprecatedSummary td { +.useSummary td, .constantsSummary td, .deprecatedSummary td, +.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td { text-align:left; padding:0px 0px 12px 10px; } -th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, -td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .useSummary th, +.constantsSummary th, .packagesSummary th, td.colFirst, td.colSecond, td.colLast, .useSummary td, +.constantsSummary td { vertical-align:top; padding-right:0px; padding-top:8px; padding-bottom:3px; } -th.colFirst, th.colLast, th.colOne, .constantsSummary th { +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .constantsSummary th, +.packagesSummary th { background:#dee3e9; text-align:left; padding:8px 3px 3px 7px; } td.colFirst, th.colFirst { - white-space:nowrap; font-size:13px; } -td.colLast, th.colLast { +td.colSecond, th.colSecond, td.colLast, th.colConstructorName, th.colDeprecatedItemName, th.colLast { font-size:13px; } -td.colOne, th.colOne { +.constantsSummary th, .packagesSummary th { + font-size:13px; +} +.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst, +.providesSummary td.colLast { + white-space:normal; font-size:13px; } .overviewSummary td.colFirst, .overviewSummary th.colFirst, -.useSummary td.colFirst, .useSummary th.colFirst, -.overviewSummary td.colOne, .overviewSummary th.colOne, +.requiresSummary td.colFirst, .requiresSummary th.colFirst, +.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th, +.usesSummary td.colFirst, .usesSummary th.colFirst, +.providesSummary td.colFirst, .providesSummary th.colFirst, .memberSummary td.colFirst, .memberSummary th.colFirst, -.memberSummary td.colOne, .memberSummary th.colOne, -.typeSummary td.colFirst{ - width:25%; +.memberSummary td.colSecond, .memberSummary th.colSecond, .memberSummary th.colConstructorName, +.typeSummary td.colFirst, .typeSummary th.colFirst { vertical-align:top; } -td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { +.packagesSummary th.colLast, .packagesSummary td.colLast { + white-space:normal; +} +td.colFirst a:link, td.colFirst a:visited, +td.colSecond a:link, td.colSecond a:visited, +th.colFirst a:link, th.colFirst a:visited, +th.colSecond a:link, th.colSecond a:visited, +th.colConstructorName a:link, th.colConstructorName a:visited, +th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited, +.constantValuesContainer td a:link, .constantValuesContainer td a:visited, +.allClassesContainer td a:link, .allClassesContainer td a:visited, +.allPackagesContainer td a:link, .allPackagesContainer td a:visited { font-weight:bold; } .tableSubHeadingColor { background-color:#EEEEFF; } -.altColor { +.altColor, .altColor th { background-color:#FFFFFF; } -.rowColor { +.rowColor, .rowColor th { background-color:#EEEEEF; } /* -Content styles -*/ + * Styles for contents. + */ .description pre { margin-top:0; } @@ -520,27 +625,22 @@ Content styles .docSummary { padding:0; } - ul.blockList ul.blockList ul.blockList li.blockList h3 { font-style:normal; } - div.block { font-size:14px; font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } - td.colLast div { padding-top:0px; } - - td.colLast a { padding-bottom:3px; } /* -Formatting effect styles -*/ + * Styles for formatting effect. + */ .sourceLineNo { color:green; padding:0 30px 0 0; @@ -555,20 +655,252 @@ h1.hidden { margin:3px 10px 2px 0px; color:#474747; } -.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { +.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink, +.moduleLabelInPackage, .moduleLabelInType, .overrideSpecifyLabel, .packageLabelInType, +.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, +.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { font-weight:bold; } .deprecationComment, .emphasizedPhrase, .interfaceName { font-style:italic; } - -div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +.deprecationBlock { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +div.block div.deprecationComment, div.block div.block span.emphasizedPhrase, div.block div.block span.interfaceName { font-style:normal; } - -div.contentContainer ul.blockList li.blockList h2{ +div.contentContainer ul.blockList li.blockList h2 { padding-bottom:0px; } +/* + * Styles for IFRAME. + */ +.mainContainer { + margin:0 auto; + padding:0; + height:100%; + width:100%; + position:fixed; + top:0; + left:0; +} +.leftContainer { + height:100%; + position:fixed; + width:320px; +} +.leftTop { + position:relative; + float:left; + width:315px; + top:0; + left:0; + height:30%; + border-right:6px solid #ccc; + border-bottom:6px solid #ccc; +} +.leftBottom { + position:relative; + float:left; + width:315px; + bottom:0; + left:0; + height:70%; + border-right:6px solid #ccc; + border-top:1px solid #000; +} +.rightContainer { + position:absolute; + left:320px; + top:0; + bottom:0; + height:100%; + right:0; + border-left:1px solid #000; +} +.rightIframe { + margin:0; + padding:0; + height:100%; + right:30px; + width:100%; + overflow:visible; + margin-bottom:30px; +} +/* + * Styles specific to HTML5 elements. + */ +main, nav, header, footer, section { + display:block; +} +/* + * Styles for javadoc search. + */ +.ui-autocomplete-category { + font-weight:bold; + font-size:15px; + padding:7px 0 7px 3px; + background-color:#4D7A97; + color:#FFFFFF; +} +.resultItem { + font-size:13px; +} +.ui-autocomplete { + max-height:85%; + max-width:65%; + overflow-y:scroll; + overflow-x:scroll; + white-space:nowrap; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); +} +ul.ui-autocomplete { + position:fixed; + z-index:999999; +} +ul.ui-autocomplete li { + float:left; + clear:both; + width:100%; +} +.resultHighlight { + font-weight:bold; +} +#search { + background-image:url('resources/glass.png'); + background-size:13px; + background-repeat:no-repeat; + background-position:2px 3px; + padding-left:20px; + position:relative; + right:-18px; +} +#reset { + background-color: rgb(255,255,255); + background-image:url('resources/x.png'); + background-position:center; + background-repeat:no-repeat; + background-size:12px; + border:0 none; + width:16px; + height:17px; + position:relative; + left:-4px; + top:-4px; + font-size:0px; +} +.watermark { + color:#545454; +} +.searchTagDescResult { + font-style:italic; + font-size:11px; +} +.searchTagHolderResult { + font-style:italic; + font-size:12px; +} +.searchTagResult:before, .searchTagResult:target { + color:red; +} +.moduleGraph span { + display:none; + position:absolute; +} +.moduleGraph:hover span { + display:block; + margin: -100px 0 0 100px; + z-index: 1; +} +.methodSignature { + white-space:normal; +} + +/* + * Styles for user-provided tables. + * + * borderless: + * No borders, vertical margins, styled caption. + * This style is provided for use with existing doc comments. + * In general, borderless tables should not be used for layout purposes. + * + * plain: + * Plain borders around table and cells, vertical margins, styled caption. + * Best for small tables or for complex tables for tables with cells that span + * rows and columns, when the "striped" style does not work well. + * + * striped: + * Borders around the table and vertical borders between cells, striped rows, + * vertical margins, styled caption. + * Best for tables that have a header row, and a body containing a series of simple rows. + */ + +table.borderless, +table.plain, +table.striped { + margin-top: 10px; + margin-bottom: 10px; +} +table.borderless > caption, +table.plain > caption, +table.striped > caption { + font-weight: bold; + font-size: smaller; +} +table.borderless th, table.borderless td, +table.plain th, table.plain td, +table.striped th, table.striped td { + padding: 2px 5px; +} +table.borderless, +table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, +table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { + border: none; +} +table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { + background-color: transparent; +} +table.plain { + border-collapse: collapse; + border: 1px solid black; +} +table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { + background-color: transparent; +} +table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, +table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { + border: 1px solid black; +} +table.striped { + border-collapse: collapse; + border: 1px solid black; +} +table.striped > thead { + background-color: #E3E3E3; +} +table.striped > thead > tr > th, table.striped > thead > tr > td { + border: 1px solid black; +} +table.striped > tbody > tr:nth-child(even) { + background-color: #EEE +} +table.striped > tbody > tr:nth-child(odd) { + background-color: #FFF +} +table.striped > tbody > tr > th, table.striped > tbody > tr > td { + border-left: 1px solid black; + border-right: 1px solid black; +} +table.striped > tbody > tr > th { + font-weight: normal; +} diff --git a/docs/acf-bukkit/type-search-index.js b/docs/acf-bukkit/type-search-index.js new file mode 100644 index 00000000..d6d85551 --- /dev/null +++ b/docs/acf-bukkit/type-search-index.js @@ -0,0 +1 @@ +typeSearchIndex = [{"p":"co.aikar.commands","l":"ACFBukkitHelpTopic"},{"p":"co.aikar.commands","l":"ACFBukkitUtil"},{"l":"All Classes","url":"allclasses-index.html"},{"p":"co.aikar.commands","l":"BukkitCommandCompletionContext"},{"p":"co.aikar.commands","l":"BukkitCommandCompletions"},{"p":"co.aikar.commands","l":"BukkitCommandContexts"},{"p":"co.aikar.commands","l":"BukkitCommandExecutionContext"},{"p":"co.aikar.commands","l":"BukkitCommandIssuer"},{"p":"co.aikar.commands","l":"BukkitCommandManager"},{"p":"co.aikar.commands","l":"BukkitConditionContext"},{"p":"co.aikar.commands","l":"BukkitLocales"},{"p":"co.aikar.commands","l":"BukkitMessageFormatter"},{"p":"co.aikar.commands","l":"BukkitRegisteredCommand"},{"p":"co.aikar.commands","l":"BukkitRootCommand"},{"p":"co.aikar.commands","l":"MinecraftMessageKeys"},{"p":"co.aikar.commands.bukkit.contexts","l":"OnlinePlayer"},{"p":"co.aikar.commands.contexts","l":"OnlinePlayer"}] \ No newline at end of file diff --git a/docs/acf-bukkit/type-search-index.zip b/docs/acf-bukkit/type-search-index.zip new file mode 100644 index 00000000..15328a5b Binary files /dev/null and b/docs/acf-bukkit/type-search-index.zip differ diff --git a/docs/acf-bungee/allclasses-index.html b/docs/acf-bungee/allclasses-index.html new file mode 100644 index 00000000..0d3e081f --- /dev/null +++ b/docs/acf-bungee/allclasses-index.html @@ -0,0 +1,231 @@ + + + + + +All Classes (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    All Classes

    +
    + +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + + diff --git a/docs/acf-bungee/allclasses.html b/docs/acf-bungee/allclasses.html new file mode 100644 index 00000000..4720006b --- /dev/null +++ b/docs/acf-bungee/allclasses.html @@ -0,0 +1,43 @@ + + + + + +All Classes (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + +

    All Classes

    +
    + +
    + + diff --git a/docs/acf-bungee/allpackages-index.html b/docs/acf-bungee/allpackages-index.html new file mode 100644 index 00000000..7d5d73b3 --- /dev/null +++ b/docs/acf-bungee/allpackages-index.html @@ -0,0 +1,173 @@ + + + + + +All Packages (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    All Packages

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + + diff --git a/docs/acf-bungee/co/aikar/commands/ACFBungeeListener.html b/docs/acf-bungee/co/aikar/commands/ACFBungeeListener.html index b6a947dc..f406ab14 100644 --- a/docs/acf-bungee/co/aikar/commands/ACFBungeeListener.html +++ b/docs/acf-bungee/co/aikar/commands/ACFBungeeListener.html @@ -1,12 +1,21 @@ - + - ACFBungeeListener (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class ACFBungeeListener

    @@ -176,64 +208,71 @@ implements net.md_5.bungee.api.plugin.Listener
    + + diff --git a/docs/acf-bungee/co/aikar/commands/ACFBungeeUtil.html b/docs/acf-bungee/co/aikar/commands/ACFBungeeUtil.html index ff656167..86890f39 100644 --- a/docs/acf-bungee/co/aikar/commands/ACFBungeeUtil.html +++ b/docs/acf-bungee/co/aikar/commands/ACFBungeeUtil.html @@ -1,12 +1,21 @@ - + - ACFBungeeUtil (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class ACFBungeeUtil

    @@ -117,120 +140,142 @@ extends
  • +
      -
    • +
    • Field Summary

      - +
      - + + - + +
      Fields 
      Modifier and TypeField and DescriptionFieldDescription
      static charCOLOR_CHAR COLOR_CHAR 
    +
    +
    +
    +
    +
  • @@ -238,12 +283,13 @@ extends
  • +
  • +
    + diff --git a/docs/acf-bungee/co/aikar/commands/BungeeCommandCompletionContext.html b/docs/acf-bungee/co/aikar/commands/BungeeCommandCompletionContext.html index 5ef29d0a..38eba8d0 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeCommandCompletionContext.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeCommandCompletionContext.html @@ -1,12 +1,21 @@ - + - BungeeCommandCompletionContext (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeCommandCompletionContext

    @@ -122,13 +145,14 @@ extends co.aikar.commands.CommandCompletionContext<
  • +
  • @@ -180,46 +210,51 @@ extends co.aikar.commands.CommandCompletionContext<
  • +
      -
    • +
    • Method Detail

      - +
      • getSender

        -
        public net.md_5.bungee.api.CommandSender getSender()
        +
        public net.md_5.bungee.api.CommandSender getSender()
      - +
      • getPlayer

        -
        public net.md_5.bungee.api.connection.ProxiedPlayer getPlayer()
        +
        public net.md_5.bungee.api.connection.ProxiedPlayer getPlayer()
    +
  • +
    + diff --git a/docs/acf-bungee/co/aikar/commands/BungeeCommandCompletions.html b/docs/acf-bungee/co/aikar/commands/BungeeCommandCompletions.html index 29028492..71e2da2d 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeCommandCompletions.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeCommandCompletions.html @@ -1,12 +1,21 @@ - + - BungeeCommandCompletions (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeCommandCompletions

    @@ -116,13 +139,14 @@ extends co.aikar.commands.CommandCompletions<
  • +
      -
    • +
    • Nested Class Summary

        -
      • +
      • Nested classes/interfaces inherited from class co.aikar.commands.CommandCompletions

        @@ -130,45 +154,52 @@ extends co.aikar.commands.CommandCompletions< +
    +
    +
  • @@ -176,37 +207,42 @@ extends co.aikar.commands.CommandCompletions<
  • +
    +
  • +
    + diff --git a/docs/acf-bungee/co/aikar/commands/BungeeCommandContexts.html b/docs/acf-bungee/co/aikar/commands/BungeeCommandContexts.html index 04dbc036..dcf656e0 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeCommandContexts.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeCommandContexts.html @@ -1,12 +1,21 @@ - + - BungeeCommandContexts (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeCommandContexts

    @@ -116,13 +139,14 @@ extends co.aikar.commands.CommandContexts<
  • +
  • +
    + diff --git a/docs/acf-bungee/co/aikar/commands/BungeeCommandExecutionContext.html b/docs/acf-bungee/co/aikar/commands/BungeeCommandExecutionContext.html index be86216d..50b9d081 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeCommandExecutionContext.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeCommandExecutionContext.html @@ -1,12 +1,21 @@ - + - BungeeCommandExecutionContext (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeCommandExecutionContext

    @@ -122,13 +145,14 @@ extends co.aikar.commands.CommandExecutionContext<
  • +
      -
    • +
    • Field Summary

        -
      • +
      • Fields inherited from class co.aikar.commands.CommandExecutionContext

        @@ -136,43 +160,49 @@ extends co.aikar.commands.CommandExecutionContext<
          -
        • +
        • Method Summary

          - +
          - + + - + + - + +
          All Methods Instance Methods Concrete Methods 
          Modifier and TypeMethod and DescriptionMethodDescription
          net.md_5.bungee.api.connection.ProxiedPlayergetPlayer() getPlayer() 
          net.md_5.bungee.api.CommandSendergetSender() getSender() 
            -
          • +
          • Methods inherited from class co.aikar.commands.CommandExecutionContext

            canOverridePlayerContext, getAnnotation, getAnnotationValue, getAnnotationValue, getArgs, getBooleanFlagValue, getBooleanFlagValue, getCmd, getDoubleFlagValue, getFirstArg, getFlags, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFloatFlagValue, getIndex, getIntFlagValue, getIssuer, getLastArg, getLongFlagValue, getNumParams, getParam, getParameterPermissions, getPassedArgs, getResolvedArg, getResolvedArg, getResolvedArg, hasAnnotation, hasFlag, isLastArg, isOptional, joinArgs, joinArgs, popFirstArg, popLastArg
        +
  • @@ -180,46 +210,51 @@ extends co.aikar.commands.CommandExecutionContext<
  • +
      -
    • +
    • Method Detail

      - +
      • getSender

        -
        public net.md_5.bungee.api.CommandSender getSender()
        +
        public net.md_5.bungee.api.CommandSender getSender()
      - +
      • getPlayer

        -
        public net.md_5.bungee.api.connection.ProxiedPlayer getPlayer()
        +
        public net.md_5.bungee.api.connection.ProxiedPlayer getPlayer()
    +
  • +
    + diff --git a/docs/acf-bungee/co/aikar/commands/BungeeCommandIssuer.html b/docs/acf-bungee/co/aikar/commands/BungeeCommandIssuer.html index 8b5aec57..95086e57 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeCommandIssuer.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeCommandIssuer.html @@ -1,12 +1,21 @@ - + - BungeeCommandIssuer (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeCommandIssuer

    @@ -193,142 +228,147 @@ implements co.aikar.commands.CommandIssuer
    • +
        -
      • +
      • Method Detail

        - +
        • getIssuer

          -
          public net.md_5.bungee.api.CommandSender getIssuer()
          +
          public net.md_5.bungee.api.CommandSender getIssuer()
          Specified by:
          getIssuer in interface co.aikar.commands.CommandIssuer
        - +
        • getPlayer

          -
          public net.md_5.bungee.api.connection.ProxiedPlayer getPlayer()
          +
          public net.md_5.bungee.api.connection.ProxiedPlayer getPlayer()
        - +
        • getManager

          -
          public co.aikar.commands.CommandManager getManager()
          +
          public co.aikar.commands.CommandManager getManager()
          Specified by:
          getManager in interface co.aikar.commands.CommandIssuer
        - +
        • isPlayer

          -
          public boolean isPlayer()
          +
          public boolean isPlayer()
          Specified by:
          isPlayer in interface co.aikar.commands.CommandIssuer
        - +
        • getUniqueId

          -
          @NotNull
          -public @NotNull UUID getUniqueId()
          +
          @NotNull
          +public @NotNull UUID getUniqueId()
          Specified by:
          getUniqueId in interface co.aikar.commands.CommandIssuer
        - + - + - + - +
      +
    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/BungeeCommandManager.html b/docs/acf-bungee/co/aikar/commands/BungeeCommandManager.html index 03f08bfe..d06f7bcf 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeCommandManager.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeCommandManager.html @@ -1,12 +1,21 @@ - + - BungeeCommandManager (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeCommandManager

    @@ -122,40 +145,47 @@ extends co.aikar.commands.CommandManager<net.md_5.bungee.api.CommandSender,
  • +
    +
      -
    • +
    • Constructor Summary

      - +
      - + + - + +
      Constructors 
      Constructor and DescriptionConstructorDescription
      BungeeCommandManager(net.md_5.bungee.api.plugin.Plugin plugin) BungeeCommandManager​(net.md_5.bungee.api.plugin.Plugin plugin) 
    +
    +
    +
  • @@ -311,12 +369,13 @@ extends co.aikar.commands.CommandManager<net.md_5.bungee.api.CommandSender,
  • +
    +
    +
    +
    +
    +
  • +
    + diff --git a/docs/acf-bungee/co/aikar/commands/BungeeConditionContext.html b/docs/acf-bungee/co/aikar/commands/BungeeConditionContext.html index cfa5fcf6..1edca8a5 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeConditionContext.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeConditionContext.html @@ -1,12 +1,21 @@ - + - BungeeConditionContext (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeConditionContext

    @@ -122,42 +145,47 @@ extends co.aikar.commands.ConditionContext<
  • +
    +
  • @@ -165,46 +193,51 @@ extends co.aikar.commands.ConditionContext<
  • +
      -
    • +
    • Method Detail

      - +
      • getSender

        -
        public net.md_5.bungee.api.CommandSender getSender()
        +
        public net.md_5.bungee.api.CommandSender getSender()
      - +
      • getPlayer

        -
        public net.md_5.bungee.api.connection.ProxiedPlayer getPlayer()
        +
        public net.md_5.bungee.api.connection.ProxiedPlayer getPlayer()
    +
  • +
    + diff --git a/docs/acf-bungee/co/aikar/commands/BungeeLocales.html b/docs/acf-bungee/co/aikar/commands/BungeeLocales.html index 8aad3dd1..793f6fb6 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeLocales.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeLocales.html @@ -1,12 +1,21 @@ - + - BungeeLocales (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeLocales

    @@ -214,50 +250,53 @@ extends co.aikar.commands.Locales +
    + diff --git a/docs/acf-bungee/co/aikar/commands/BungeeMessageFormatter.html b/docs/acf-bungee/co/aikar/commands/BungeeMessageFormatter.html index 1663e3ba..ca05813e 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeMessageFormatter.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeMessageFormatter.html @@ -1,12 +1,21 @@ - + - BungeeMessageFormatter (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeMessageFormatter

    @@ -161,37 +190,42 @@ extends co.aikar.commands.MessageFormatter<net.md_5.bungee.api.ChatColor>< +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    diff --git a/docs/acf-bungee/co/aikar/commands/BungeeRegisteredCommand.html b/docs/acf-bungee/co/aikar/commands/BungeeRegisteredCommand.html index 6f1e64a0..c96466a1 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeRegisteredCommand.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeRegisteredCommand.html @@ -1,12 +1,21 @@ - + - BungeeRegisteredCommand (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeRegisteredCommand

    @@ -122,13 +145,14 @@ extends co.aikar.commands.RegisteredCommand<
  • +
  • @@ -180,54 +210,59 @@ extends co.aikar.commands.RegisteredCommand<
  • +
    +
  • +
    + diff --git a/docs/acf-bungee/co/aikar/commands/BungeeRootCommand.html b/docs/acf-bungee/co/aikar/commands/BungeeRootCommand.html index 6d4195f1..25ef182a 100644 --- a/docs/acf-bungee/co/aikar/commands/BungeeRootCommand.html +++ b/docs/acf-bungee/co/aikar/commands/BungeeRootCommand.html @@ -1,12 +1,21 @@ - + - BungeeRootCommand (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BungeeRootCommand

    @@ -207,124 +242,125 @@ implements co.aikar.commands.RootCommand, net.md_5.bungee.api.plugin.TabExecutor
    • +
        -
      • +
      • Method Detail

        - + - +
        • addChild

          -
          public void addChild(co.aikar.commands.BaseCommand command)
          +
          public void addChild​(co.aikar.commands.BaseCommand command)
          Specified by:
          addChild in interface co.aikar.commands.RootCommand
        - +
        • getManager

          -
          public co.aikar.commands.CommandManager getManager()
          +
          public co.aikar.commands.CommandManager getManager()
          Specified by:
          getManager in interface co.aikar.commands.RootCommand
        - +
        • getSubCommands

          -
          public com.google.common.collect.SetMultimap<String,co.aikar.commands.RegisteredCommand> getSubCommands()
          +
          public com.google.common.collect.SetMultimap<String,​co.aikar.commands.RegisteredCommand> getSubCommands()
          Specified by:
          getSubCommands in interface co.aikar.commands.RootCommand
        - +
        • getChildren

          -
          public List<co.aikar.commands.BaseCommand> getChildren()
          +
          public List<co.aikar.commands.BaseCommand> getChildren()
          Specified by:
          getChildren in interface co.aikar.commands.RootCommand
        - +
        • execute

          -
          public void execute(net.md_5.bungee.api.CommandSender sender,
          -                    String[] args)
          +
          public void execute​(net.md_5.bungee.api.CommandSender sender,
          +                    String[] args)
          Specified by:
          execute in class net.md_5.bungee.api.plugin.Command
        - + - + - +
        • getDefCommand

          -
          public co.aikar.commands.BaseCommand getDefCommand()
          +
          public co.aikar.commands.BaseCommand getDefCommand()
          Specified by:
          getDefCommand in interface co.aikar.commands.RootCommand
          @@ -333,21 +369,25 @@ implements co.aikar.commands.RootCommand, net.md_5.bungee.api.plugin.TabExecutor
      +
    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/MinecraftMessageKeys.html b/docs/acf-bungee/co/aikar/commands/MinecraftMessageKeys.html index b6165263..9915fb48 100644 --- a/docs/acf-bungee/co/aikar/commands/MinecraftMessageKeys.html +++ b/docs/acf-bungee/co/aikar/commands/MinecraftMessageKeys.html @@ -1,12 +1,21 @@ - + - MinecraftMessageKeys (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Enum MinecraftMessageKeys

    @@ -208,73 +245,76 @@ the order they are declared. +
    + diff --git a/docs/acf-bungee/co/aikar/commands/bungee/contexts/OnlinePlayer.html b/docs/acf-bungee/co/aikar/commands/bungee/contexts/OnlinePlayer.html index 3ad36d68..1c8c4dcc 100644 --- a/docs/acf-bungee/co/aikar/commands/bungee/contexts/OnlinePlayer.html +++ b/docs/acf-bungee/co/aikar/commands/bungee/contexts/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - OnlinePlayer (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands.bungee.contexts
    +

    Class OnlinePlayer

    @@ -121,79 +144,94 @@ extends
  • +
      -
    • +
    • Field Summary

      - +
      - + + - + +
      Fields 
      Modifier and TypeField and DescriptionFieldDescription
      net.md_5.bungee.api.connection.ProxiedPlayerplayer player 
    +
    +
      -
    • +
    • Constructor Summary

      - +
      - + + - + +
      Constructors 
      Constructor and DescriptionConstructorDescription
      OnlinePlayer(net.md_5.bungee.api.connection.ProxiedPlayer player) OnlinePlayer​(net.md_5.bungee.api.connection.ProxiedPlayer player) 
    +
    +
    +
  • @@ -201,12 +239,13 @@ extends
  • +
      -
    • +
    • Field Detail

      - +
        @@ -217,94 +256,102 @@ extends
          -
        • +
        • Constructor Detail

          - +
          • OnlinePlayer

            -
            public OnlinePlayer(net.md_5.bungee.api.connection.ProxiedPlayer player)
            +
            public OnlinePlayer​(net.md_5.bungee.api.connection.ProxiedPlayer player)
        +
    +
    +
  • +
    + diff --git a/docs/acf-bungee/co/aikar/commands/bungee/contexts/class-use/OnlinePlayer.html b/docs/acf-bungee/co/aikar/commands/bungee/contexts/class-use/OnlinePlayer.html index b5627f06..54de9b31 100644 --- a/docs/acf-bungee/co/aikar/commands/bungee/contexts/class-use/OnlinePlayer.html +++ b/docs/acf-bungee/co/aikar/commands/bungee/contexts/class-use/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.bungee.contexts.OnlinePlayer (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.bungee.contexts.OnlinePlayer

  • + + diff --git a/docs/acf-bungee/co/aikar/commands/bungee/contexts/package-summary.html b/docs/acf-bungee/co/aikar/commands/bungee/contexts/package-summary.html index fd0c9d31..f55419a5 100644 --- a/docs/acf-bungee/co/aikar/commands/bungee/contexts/package-summary.html +++ b/docs/acf-bungee/co/aikar/commands/bungee/contexts/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.bungee.contexts (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Package co.aikar.commands.bungee.contexts

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/ACFBungeeListener.html b/docs/acf-bungee/co/aikar/commands/class-use/ACFBungeeListener.html index 3c32b1eb..c20d0ba3 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/ACFBungeeListener.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/ACFBungeeListener.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ACFBungeeListener (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.ACFBungeeListener

    No usage of co.aikar.commands.ACFBungeeListener
    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/ACFBungeeUtil.html b/docs/acf-bungee/co/aikar/commands/class-use/ACFBungeeUtil.html index 38bc2639..330bf105 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/ACFBungeeUtil.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/ACFBungeeUtil.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ACFBungeeUtil (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.ACFBungeeUtil

    No usage of co.aikar.commands.ACFBungeeUtil
    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandCompletionContext.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandCompletionContext.html index 5276d1b1..2e512fcc 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandCompletionContext.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandCompletionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeCommandCompletionContext (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeCommandCompletionContext

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandCompletions.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandCompletions.html index c29377aa..84cdaedc 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandCompletions.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandCompletions.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeCommandCompletions (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeCommandCompletions

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandContexts.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandContexts.html index 92d48cb0..82397138 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandContexts.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandContexts.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeCommandContexts (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeCommandContexts

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandExecutionContext.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandExecutionContext.html index d8947b75..b0ab734d 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandExecutionContext.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandExecutionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeCommandExecutionContext (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeCommandExecutionContext

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandIssuer.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandIssuer.html index 212c833d..86eb4885 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandIssuer.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandIssuer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeCommandIssuer (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeCommandIssuer

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandManager.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandManager.html index 1f14f05e..6d311d51 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandManager.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeCommandManager.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeCommandManager (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeCommandManager

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeConditionContext.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeConditionContext.html index 22be85a8..bc3ebbc6 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeConditionContext.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeConditionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeConditionContext (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeConditionContext

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeLocales.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeLocales.html index 72633102..eb529202 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeLocales.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeLocales.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeLocales (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeLocales

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeMessageFormatter.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeMessageFormatter.html index c028a231..03a01316 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeMessageFormatter.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeMessageFormatter.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeMessageFormatter (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeMessageFormatter

    No usage of co.aikar.commands.BungeeMessageFormatter
    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeRegisteredCommand.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeRegisteredCommand.html index 0e9daa21..0fefe81d 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeRegisteredCommand.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeRegisteredCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeRegisteredCommand (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeRegisteredCommand

    No usage of co.aikar.commands.BungeeRegisteredCommand
    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/BungeeRootCommand.html b/docs/acf-bungee/co/aikar/commands/class-use/BungeeRootCommand.html index 29c6f5a9..38c6749c 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/BungeeRootCommand.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/BungeeRootCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BungeeRootCommand (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.BungeeRootCommand

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/class-use/MinecraftMessageKeys.html b/docs/acf-bungee/co/aikar/commands/class-use/MinecraftMessageKeys.html index 330392ee..3f45b4ae 100644 --- a/docs/acf-bungee/co/aikar/commands/class-use/MinecraftMessageKeys.html +++ b/docs/acf-bungee/co/aikar/commands/class-use/MinecraftMessageKeys.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.MinecraftMessageKeys (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.MinecraftMessageKeys

    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/contexts/OnlineProxiedPlayer.html b/docs/acf-bungee/co/aikar/commands/contexts/OnlineProxiedPlayer.html index 998da405..868f1ea5 100644 --- a/docs/acf-bungee/co/aikar/commands/contexts/OnlineProxiedPlayer.html +++ b/docs/acf-bungee/co/aikar/commands/contexts/OnlineProxiedPlayer.html @@ -1,12 +1,21 @@ - + - OnlineProxiedPlayer (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands.contexts
    +

    Class OnlineProxiedPlayer

    @@ -120,61 +143,69 @@ extends
  • +
    +
    +
      -
    • +
    • Constructor Summary

      - +
      - + + - +
      Constructors 
      Constructor and DescriptionConstructorDescription
      OnlineProxiedPlayer(net.md_5.bungee.api.connection.ProxiedPlayer player) -
      Deprecated. 
      +
      OnlineProxiedPlayer​(net.md_5.bungee.api.connection.ProxiedPlayer player) +
      Deprecated.
       
    +
    +
    +
  • @@ -182,38 +213,43 @@ extends
  • +
      -
    • +
    • Constructor Detail

      - +
      • OnlineProxiedPlayer

        -
        public OnlineProxiedPlayer(net.md_5.bungee.api.connection.ProxiedPlayer player)
        -
        Deprecated. 
        +
        public OnlineProxiedPlayer​(net.md_5.bungee.api.connection.ProxiedPlayer player)
        +
        Deprecated.
    +
  • +
    + diff --git a/docs/acf-bungee/co/aikar/commands/contexts/class-use/OnlineProxiedPlayer.html b/docs/acf-bungee/co/aikar/commands/contexts/class-use/OnlineProxiedPlayer.html index a90f3c3c..8cdf527a 100644 --- a/docs/acf-bungee/co/aikar/commands/contexts/class-use/OnlineProxiedPlayer.html +++ b/docs/acf-bungee/co/aikar/commands/contexts/class-use/OnlineProxiedPlayer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.contexts.OnlineProxiedPlayer (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.contexts.OnlineProxiedPlayer

    No usage of co.aikar.commands.contexts.OnlineProxiedPlayer
    +
    + diff --git a/docs/acf-bungee/co/aikar/commands/contexts/package-summary.html b/docs/acf-bungee/co/aikar/commands/contexts/package-summary.html index 450b4d17..9586caaa 100644 --- a/docs/acf-bungee/co/aikar/commands/contexts/package-summary.html +++ b/docs/acf-bungee/co/aikar/commands/contexts/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.contexts (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Package co.aikar.commands.contexts

    +
    + diff --git a/docs/acf-bungee/constant-values.html b/docs/acf-bungee/constant-values.html index 6afd58f5..ad2272b8 100644 --- a/docs/acf-bungee/constant-values.html +++ b/docs/acf-bungee/constant-values.html @@ -1,12 +1,21 @@ - + - Constant Field Values (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Constant Field Values

    +

    Contents

    +
    -
    +
    +

    co.aikar.*

    +
    +
    + diff --git a/docs/acf-bungee/deprecated-list.html b/docs/acf-bungee/deprecated-list.html index f7656db1..8ea42f04 100644 --- a/docs/acf-bungee/deprecated-list.html +++ b/docs/acf-bungee/deprecated-list.html @@ -1,12 +1,21 @@ - + - Deprecated List (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    + diff --git a/docs/acf-bungee/element-list b/docs/acf-bungee/element-list new file mode 100644 index 00000000..4972251f --- /dev/null +++ b/docs/acf-bungee/element-list @@ -0,0 +1,3 @@ +co.aikar.commands +co.aikar.commands.bungee.contexts +co.aikar.commands.contexts diff --git a/docs/acf-bungee/index-all.html b/docs/acf-bungee/index-all.html index 7581de0c..97c77928 100644 --- a/docs/acf-bungee/index-all.html +++ b/docs/acf-bungee/index-all.html @@ -1,12 +1,21 @@ - + - Index (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    +
    A B C E F G H I L M N O P R S T U V 
    All Classes All Packages

    A

    ACFBungeeListener - Class in co.aikar.commands
     
    -
    ACFBungeeListener(BungeeCommandManager, Plugin) - Constructor for class co.aikar.commands.ACFBungeeListener
    +
    ACFBungeeListener(BungeeCommandManager, Plugin) - Constructor for class co.aikar.commands.ACFBungeeListener
     
    ACFBungeeUtil - Class in co.aikar.commands
     
    -
    ACFBungeeUtil() - Constructor for class co.aikar.commands.ACFBungeeUtil
    +
    ACFBungeeUtil() - Constructor for class co.aikar.commands.ACFBungeeUtil
     
    -
    addChild(BaseCommand) - Method in class co.aikar.commands.BungeeRootCommand
    +
    addChild(BaseCommand) - Method in class co.aikar.commands.BungeeRootCommand
     
    - +

    B

    @@ -93,7 +117,7 @@
     
    BungeeCommandCompletions - Class in co.aikar.commands
     
    -
    BungeeCommandCompletions(CommandManager) - Constructor for class co.aikar.commands.BungeeCommandCompletions
    +
    BungeeCommandCompletions(CommandManager) - Constructor for class co.aikar.commands.BungeeCommandCompletions
     
    BungeeCommandContexts - Class in co.aikar.commands
     
    @@ -103,24 +127,24 @@
     
    BungeeCommandManager - Class in co.aikar.commands
     
    -
    BungeeCommandManager(Plugin) - Constructor for class co.aikar.commands.BungeeCommandManager
    +
    BungeeCommandManager(Plugin) - Constructor for class co.aikar.commands.BungeeCommandManager
     
    BungeeConditionContext - Class in co.aikar.commands
     
    BungeeLocales - Class in co.aikar.commands
     
    -
    BungeeLocales(BungeeCommandManager) - Constructor for class co.aikar.commands.BungeeLocales
    +
    BungeeLocales(BungeeCommandManager) - Constructor for class co.aikar.commands.BungeeLocales
     
    BungeeMessageFormatter - Class in co.aikar.commands
     
    -
    BungeeMessageFormatter(ChatColor...) - Constructor for class co.aikar.commands.BungeeMessageFormatter
    +
    BungeeMessageFormatter(ChatColor...) - Constructor for class co.aikar.commands.BungeeMessageFormatter
     
    BungeeRegisteredCommand - Class in co.aikar.commands
     
    BungeeRootCommand - Class in co.aikar.commands
     
    - +

    C

    @@ -131,7 +155,7 @@
     
    co.aikar.commands.contexts - package co.aikar.commands.contexts
     
    -
    color(String) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    color(String) - Static method in class co.aikar.commands.ACFBungeeUtil
     
    COLOR_CHAR - Static variable in class co.aikar.commands.ACFBungeeUtil
     
    @@ -139,186 +163,200 @@
     
    contexts - Variable in class co.aikar.commands.BungeeCommandManager
     
    -
    createCommandContext(RegisteredCommand, CommandParameter, CommandIssuer, List<String>, int, Map<String, Object>) - Method in class co.aikar.commands.BungeeCommandManager
    +
    createCommandContext(RegisteredCommand, CommandParameter, CommandIssuer, List<String>, int, Map<String, Object>) - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    createCompletionContext(RegisteredCommand, CommandIssuer, String, String, String[]) - Method in class co.aikar.commands.BungeeCommandManager
    +
    createCompletionContext(RegisteredCommand, CommandIssuer, String, String, String[]) - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    createConditionContext(CommandIssuer, String) - Method in class co.aikar.commands.BungeeCommandManager
    +
    createConditionContext(CommandIssuer, String) - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    createRegisteredCommand(BaseCommand, String, Method, String) - Method in class co.aikar.commands.BungeeCommandManager
    +
    createRegisteredCommand(BaseCommand, String, Method, String) - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    createRootCommand(String) - Method in class co.aikar.commands.BungeeCommandManager
    +
    createRootCommand(String) - Method in class co.aikar.commands.BungeeCommandManager
     
    - +

    E

    -
    equals(Object) - Method in class co.aikar.commands.bungee.contexts.OnlinePlayer
    +
    equals(Object) - Method in class co.aikar.commands.bungee.contexts.OnlinePlayer
     
    -
    equals(Object) - Method in class co.aikar.commands.BungeeCommandIssuer
    +
    equals(Object) - Method in class co.aikar.commands.BungeeCommandIssuer
     
    -
    execute(CommandSender, String[]) - Method in class co.aikar.commands.BungeeRootCommand
    +
    execute(CommandSender, String[]) - Method in class co.aikar.commands.BungeeRootCommand
     
    - +

    F

    -
    findPlayerSmart(CommandIssuer, String) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    findPlayerSmart(CommandIssuer, String) - Static method in class co.aikar.commands.ACFBungeeUtil
     
    -
    findPlayerSmart(CommandSender, String) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    findPlayerSmart(CommandSender, String) - Static method in class co.aikar.commands.ACFBungeeUtil
    -
    Deprecated. 
    +
    Deprecated. 
    - +

    G

    -
    getChildren() - Method in class co.aikar.commands.BungeeRootCommand
    +
    getChildren() - Method in class co.aikar.commands.BungeeRootCommand
     
    -
    getCommandCompletions() - Method in class co.aikar.commands.BungeeCommandManager
    +
    getCommandCompletions() - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    getCommandContexts() - Method in class co.aikar.commands.BungeeCommandManager
    +
    getCommandContexts() - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    getCommandIssuer(Object) - Method in class co.aikar.commands.BungeeCommandManager
    +
    getCommandIssuer(Object) - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    getCommandName() - Method in class co.aikar.commands.BungeeRootCommand
    +
    getCommandName() - Method in class co.aikar.commands.BungeeRootCommand
     
    -
    getCommandPrefix(CommandIssuer) - Method in class co.aikar.commands.BungeeCommandManager
    +
    getCommandPrefix(CommandIssuer) - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    getDefCommand() - Method in class co.aikar.commands.BungeeRootCommand
    +
    getDefCommand() - Method in class co.aikar.commands.BungeeRootCommand
     
    -
    getIssuer() - Method in class co.aikar.commands.BungeeCommandIssuer
    +
    getIssuer() - Method in class co.aikar.commands.BungeeCommandIssuer
     
    -
    getLastColors(String) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    getLastColors(String) - Static method in class co.aikar.commands.ACFBungeeUtil
     
    -
    getLocales() - Method in class co.aikar.commands.BungeeCommandManager
    +
    getLocales() - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    getManager() - Method in class co.aikar.commands.BungeeCommandIssuer
    +
    getManager() - Method in class co.aikar.commands.BungeeCommandIssuer
     
    -
    getManager() - Method in class co.aikar.commands.BungeeRootCommand
    +
    getManager() - Method in class co.aikar.commands.BungeeRootCommand
     
    -
    getMessageKey() - Method in enum co.aikar.commands.MinecraftMessageKeys
    +
    getMessageKey() - Method in enum co.aikar.commands.MinecraftMessageKeys
     
    -
    getPermission() - Method in class co.aikar.commands.BungeeRootCommand
    +
    getPermission() - Method in class co.aikar.commands.BungeeRootCommand
     
    -
    getPlayer() - Method in class co.aikar.commands.bungee.contexts.OnlinePlayer
    +
    getPlayer() - Method in class co.aikar.commands.bungee.contexts.OnlinePlayer
     
    -
    getPlayer() - Method in class co.aikar.commands.BungeeCommandCompletionContext
    +
    getPlayer() - Method in class co.aikar.commands.BungeeCommandCompletionContext
     
    -
    getPlayer() - Method in class co.aikar.commands.BungeeCommandExecutionContext
    +
    getPlayer() - Method in class co.aikar.commands.BungeeCommandExecutionContext
     
    -
    getPlayer() - Method in class co.aikar.commands.BungeeCommandIssuer
    +
    getPlayer() - Method in class co.aikar.commands.BungeeCommandIssuer
     
    -
    getPlayer() - Method in class co.aikar.commands.BungeeConditionContext
    +
    getPlayer() - Method in class co.aikar.commands.BungeeConditionContext
     
    -
    getPlugin() - Method in class co.aikar.commands.BungeeCommandManager
    +
    getPlugin() - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    getRegisteredRootCommands() - Method in class co.aikar.commands.BungeeCommandManager
    +
    getRegisteredRootCommands() - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    getSender() - Method in class co.aikar.commands.BungeeCommandCompletionContext
    +
    getSender() - Method in class co.aikar.commands.BungeeCommandCompletionContext
     
    -
    getSender() - Method in class co.aikar.commands.BungeeCommandExecutionContext
    +
    getSender() - Method in class co.aikar.commands.BungeeCommandExecutionContext
     
    -
    getSender() - Method in class co.aikar.commands.BungeeConditionContext
    +
    getSender() - Method in class co.aikar.commands.BungeeConditionContext
     
    -
    getSubCommands() - Method in class co.aikar.commands.BungeeRootCommand
    +
    getSubCommands() - Method in class co.aikar.commands.BungeeRootCommand
     
    -
    getUniqueId() - Method in class co.aikar.commands.BungeeCommandIssuer
    +
    getUniqueId() - Method in class co.aikar.commands.BungeeCommandIssuer
     
    - +

    H

    -
    hashCode() - Method in class co.aikar.commands.bungee.contexts.OnlinePlayer
    +
    hashCode() - Method in class co.aikar.commands.bungee.contexts.OnlinePlayer
     
    -
    hashCode() - Method in class co.aikar.commands.BungeeCommandIssuer
    +
    hashCode() - Method in class co.aikar.commands.BungeeCommandIssuer
     
    -
    hasPermission(String) - Method in class co.aikar.commands.BungeeCommandIssuer
    +
    hasPermission(String) - Method in class co.aikar.commands.BungeeCommandIssuer
     
    -
    hasRegisteredCommands() - Method in class co.aikar.commands.BungeeCommandManager
    +
    hasRegisteredCommands() - Method in class co.aikar.commands.BungeeCommandManager
     
    - +

    I

    -
    isChatColorAColor(ChatColor) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    IS_NOT_A_VALID_NAME - co.aikar.commands.MinecraftMessageKeys
     
    -
    isCommandIssuer(Class<?>) - Method in class co.aikar.commands.BungeeCommandManager
    +
    isChatColorAColor(ChatColor) - Static method in class co.aikar.commands.ACFBungeeUtil
     
    -
    isPlayer() - Method in class co.aikar.commands.BungeeCommandIssuer
    +
    isCommandIssuer(Class<?>) - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    isValidName(String) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    isPlayer() - Method in class co.aikar.commands.BungeeCommandIssuer
    +
     
    +
    isValidName(String) - Static method in class co.aikar.commands.ACFBungeeUtil
     
    - +

    L

    -
    loadLanguage(Configuration, Locale) - Method in class co.aikar.commands.BungeeLocales
    +
    loadLanguage(Configuration, Locale) - Method in class co.aikar.commands.BungeeLocales
    Loads every message from the Configuration object.
    -
    loadLanguages() - Method in class co.aikar.commands.BungeeLocales
    +
    loadLanguages() - Method in class co.aikar.commands.BungeeLocales
     
    -
    loadYamlLanguageFile(File, Locale) - Method in class co.aikar.commands.BungeeLocales
    +
    loadYamlLanguageFile(File, Locale) - Method in class co.aikar.commands.BungeeLocales
    Loads the given file
    -
    loadYamlLanguageFile(String, Locale) - Method in class co.aikar.commands.BungeeLocales
    +
    loadYamlLanguageFile(String, Locale) - Method in class co.aikar.commands.BungeeLocales
    Loads a file out of the plugins data folder by the given name
    locales - Variable in class co.aikar.commands.BungeeCommandManager
     
    -
    log(LogLevel, String, Throwable) - Method in class co.aikar.commands.BungeeCommandManager
    +
    log(LogLevel, String, Throwable) - Method in class co.aikar.commands.BungeeCommandManager
     
    - +

    M

    MinecraftMessageKeys - Enum in co.aikar.commands
     
    +
    MULTIPLE_PLAYERS_MATCH - co.aikar.commands.MinecraftMessageKeys
    +
     
    - + + + +

    N

    +
    +
    NO_PLAYER_FOUND - co.aikar.commands.MinecraftMessageKeys
    +
     
    +
    NO_PLAYER_FOUND_SERVER - co.aikar.commands.MinecraftMessageKeys
    +
     
    +
    +

    O

    -
    onDisconnect(PlayerDisconnectEvent) - Method in class co.aikar.commands.ACFBungeeListener
    +
    onDisconnect(PlayerDisconnectEvent) - Method in class co.aikar.commands.ACFBungeeListener
     
    OnlinePlayer - Class in co.aikar.commands.bungee.contexts
     
    -
    OnlinePlayer(ProxiedPlayer) - Constructor for class co.aikar.commands.bungee.contexts.OnlinePlayer
    +
    OnlinePlayer(ProxiedPlayer) - Constructor for class co.aikar.commands.bungee.contexts.OnlinePlayer
     
    OnlineProxiedPlayer - Class in co.aikar.commands.contexts
    -
    Deprecated. - +
    Deprecated. +
    -
    OnlineProxiedPlayer(ProxiedPlayer) - Constructor for class co.aikar.commands.contexts.OnlineProxiedPlayer
    +
    OnlineProxiedPlayer(ProxiedPlayer) - Constructor for class co.aikar.commands.contexts.OnlineProxiedPlayer
    -
    Deprecated.
    +
    Deprecated.
     
    -
    onPlayerJoin(PostLoginEvent) - Method in class co.aikar.commands.ACFBungeeListener
    +
    onPlayerJoin(PostLoginEvent) - Method in class co.aikar.commands.ACFBungeeListener
     
    -
    onTabComplete(CommandSender, String[]) - Method in class co.aikar.commands.BungeeRootCommand
    +
    onTabComplete(CommandSender, String[]) - Method in class co.aikar.commands.BungeeRootCommand
     
    - +

    P

    @@ -327,89 +365,94 @@
     
    plugin - Variable in class co.aikar.commands.BungeeCommandManager
     
    -
    postCommand() - Method in class co.aikar.commands.BungeeRegisteredCommand
    +
    postCommand() - Method in class co.aikar.commands.BungeeRegisteredCommand
     
    -
    preCommand() - Method in class co.aikar.commands.BungeeRegisteredCommand
    +
    preCommand() - Method in class co.aikar.commands.BungeeRegisteredCommand
     
    - +

    R

    -
    readLocale(ProxiedPlayer) - Method in class co.aikar.commands.BungeeCommandManager
    +
    readLocale(ProxiedPlayer) - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    registerCommand(BaseCommand) - Method in class co.aikar.commands.BungeeCommandManager
    +
    registerCommand(BaseCommand) - Method in class co.aikar.commands.BungeeCommandManager
     
    registeredCommands - Variable in class co.aikar.commands.BungeeCommandManager
     
    -
    removeColors(String) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    removeColors(String) - Static method in class co.aikar.commands.ACFBungeeUtil
     
    -
    replaceChatString(String, String, String) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    replaceChatString(String, String, String) - Static method in class co.aikar.commands.ACFBungeeUtil
     
    -
    replaceChatString(String, Pattern, String) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    replaceChatString(String, Pattern, String) - Static method in class co.aikar.commands.ACFBungeeUtil
     
    - +

    S

    -
    sendMessageInternal(String) - Method in class co.aikar.commands.BungeeCommandIssuer
    +
    sendMessageInternal(String) - Method in class co.aikar.commands.BungeeCommandIssuer
     
    -
    sendMsg(CommandSender, String) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    sendMsg(CommandSender, String) - Static method in class co.aikar.commands.ACFBungeeUtil
    -
    Deprecated. 
    +
    Deprecated. 
    - +

    T

    -
    toString() - Method in class co.aikar.commands.bungee.contexts.OnlinePlayer
    +
    toString() - Method in class co.aikar.commands.bungee.contexts.OnlinePlayer
     
    - +

    U

    -
    unregisterCommand(BaseCommand) - Method in class co.aikar.commands.BungeeCommandManager
    +
    unregisterCommand(BaseCommand) - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    unregisterCommand(BungeeRootCommand) - Method in class co.aikar.commands.BungeeCommandManager
    +
    unregisterCommand(BungeeRootCommand) - Method in class co.aikar.commands.BungeeCommandManager
     
    -
    unregisterCommands() - Method in class co.aikar.commands.BungeeCommandManager
    +
    unregisterCommands() - Method in class co.aikar.commands.BungeeCommandManager
    +
     
    +
    USERNAME_TOO_SHORT - co.aikar.commands.MinecraftMessageKeys
     
    - +

    V

    -
    validate(T, String, Object...) - Static method in class co.aikar.commands.ACFBungeeUtil
    +
    validate(T, String, Object...) - Static method in class co.aikar.commands.ACFBungeeUtil
     
    -
    valueOf(String) - Static method in enum co.aikar.commands.MinecraftMessageKeys
    +
    valueOf(String) - Static method in enum co.aikar.commands.MinecraftMessageKeys
    Returns the enum constant of this type with the specified name.
    -
    values() - Static method in enum co.aikar.commands.MinecraftMessageKeys
    +
    values() - Static method in enum co.aikar.commands.MinecraftMessageKeys
    Returns an array containing the constants of this enum type, in the order they are declared.
    -A B C E F G H I L M O P R S T U V 
    +A B C E F G H I L M N O P R S T U V 
    All Classes All Packages +
    + diff --git a/docs/acf-bungee/index.html b/docs/acf-bungee/index.html index a41c21f8..c2fd604a 100644 --- a/docs/acf-bungee/index.html +++ b/docs/acf-bungee/index.html @@ -1,76 +1,169 @@ - + +Overview (ACF (Bungee) 0.5.0-SNAPSHOT API) -ACF (Bungee) 0.5.0-SNAPSHOT API - + + + + + + + + + - - - - - - - +<body> +<script type="text/javascript"><!-- + try { + if (location.href.indexOf('is-external=true') == -1) { + parent.document.title="Overview (ACF (Bungee) 0.5.0-SNAPSHOT API)"; + } + } + catch(err) { + } +//--> +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script');</script> <noscript> <div>JavaScript is disabled on your browser.</div> </noscript> -<h2>Frame Alert</h2> -<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p> - - +
    + +
    +
    +

    ACF (Bungee) 0.5.0-SNAPSHOT API

    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + +
    Packages 
    PackageDescription
    co.aikar.commands 
    co.aikar.commands.bungee.contexts 
    co.aikar.commands.contexts 
    +
    +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + diff --git a/docs/acf-bungee/jquery/external/jquery/jquery.js b/docs/acf-bungee/jquery/external/jquery/jquery.js new file mode 100644 index 00000000..9b5206bc --- /dev/null +++ b/docs/acf-bungee/jquery/external/jquery/jquery.js @@ -0,0 +1,10364 @@ +/*! + * jQuery JavaScript Library v3.3.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2018-01-20T17:24Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + + + + var preservedScriptAttributes = { + type: true, + src: true, + noModule: true + }; + + function DOMEval( code, doc, node ) { + doc = doc || document; + + var i, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + if ( node[ i ] ) { + script[ i ] = node[ i ]; + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.3.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && Array.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( nodeName( elem, "iframe" ) ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
    " ], + col: [ 2, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + div.style.position = "absolute"; + scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a property mapped along what jQuery.cssProps suggests or to +// a vendor prefixed property. +function finalPropName( name ) { + var ret = jQuery.cssProps[ name ]; + if ( !ret ) { + ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + } + return ret; +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + ) ); + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + val = curCSS( elem, dimension, styles ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox; + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = valueIsBorderBox && + ( support.boxSizingReliable() || val === elem.style[ dimension ] ); + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + if ( val === "auto" || + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { + + val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; + + // offsetWidth/offsetHeight provide border-box values + valueIsBorderBox = true; + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra && boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ); + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && support.scrollboxSize() === styles.position ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = Date.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "\r\n"; + +// inject VBScript +document.write(IEBinaryToArray_ByteStr_Script); + +global.JSZipUtils._getBinaryFromXHR = function (xhr) { + var binary = xhr.responseBody; + var byteMapping = {}; + for ( var i = 0; i < 256; i++ ) { + for ( var j = 0; j < 256; j++ ) { + byteMapping[ String.fromCharCode( i + (j << 8) ) ] = + String.fromCharCode(i) + String.fromCharCode(j); + } + } + var rawBytes = IEBinaryToArray_ByteStr(binary); + var lastChr = IEBinaryToArray_ByteStr_Last(binary); + return rawBytes.replace(/[\s\S]/g, function( match ) { + return byteMapping[match]; + }) + lastChr; +}; + +// enforcing Stuk's coding style +// vim: set shiftwidth=4 softtabstop=4: + +},{}]},{},[1]) +; diff --git a/docs/acf-bungee/jquery/jszip-utils/dist/jszip-utils-ie.min.js b/docs/acf-bungee/jquery/jszip-utils/dist/jszip-utils-ie.min.js new file mode 100644 index 00000000..93d8bc8e --- /dev/null +++ b/docs/acf-bungee/jquery/jszip-utils/dist/jszip-utils-ie.min.js @@ -0,0 +1,10 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); diff --git a/docs/acf-bungee/jquery/jszip-utils/dist/jszip-utils.js b/docs/acf-bungee/jquery/jszip-utils/dist/jszip-utils.js new file mode 100644 index 00000000..775895ec --- /dev/null +++ b/docs/acf-bungee/jquery/jszip-utils/dist/jszip-utils.js @@ -0,0 +1,118 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ + +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64; + enc4 = remainingBytes > 2 ? (chr3 & 63) : 64; + + output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4)); + + } + + return output.join(""); +}; + +// public method for decoding +exports.decode = function(input) { + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0, resultIndex = 0; + + var dataUrlPrefix = "data:"; + + if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) { + // This is a common error: people give a data url + // (data:image/png;base64,iVBOR...) with a {base64: true} and + // wonders why things don't work. + // We can detect that the string input looks like a data url but we + // *can't* be sure it is one: removing everything up to the comma would + // be too dangerous. + throw new Error("Invalid base64 input, it looks like a data url."); + } + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + var totalLength = input.length * 3 / 4; + if(input.charAt(input.length - 1) === _keyStr.charAt(64)) { + totalLength--; + } + if(input.charAt(input.length - 2) === _keyStr.charAt(64)) { + totalLength--; + } + if (totalLength % 1 !== 0) { + // totalLength is not an integer, the length does not match a valid + // base64 content. That can happen if: + // - the input is not a base64 content + // - the input is *almost* a base64 content, with a extra chars at the + // beginning or at the end + // - the input uses a base64 variant (base64url for example) + throw new Error("Invalid base64 input, bad content length."); + } + var output; + if (support.uint8array) { + output = new Uint8Array(totalLength|0); + } else { + output = new Array(totalLength|0); + } + + while (i < input.length) { + + enc1 = _keyStr.indexOf(input.charAt(i++)); + enc2 = _keyStr.indexOf(input.charAt(i++)); + enc3 = _keyStr.indexOf(input.charAt(i++)); + enc4 = _keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output[resultIndex++] = chr1; + + if (enc3 !== 64) { + output[resultIndex++] = chr2; + } + if (enc4 !== 64) { + output[resultIndex++] = chr3; + } + + } + + return output; +}; + +},{"./support":30,"./utils":32}],2:[function(require,module,exports){ +'use strict'; + +var external = require("./external"); +var DataWorker = require('./stream/DataWorker'); +var DataLengthProbe = require('./stream/DataLengthProbe'); +var Crc32Probe = require('./stream/Crc32Probe'); +var DataLengthProbe = require('./stream/DataLengthProbe'); + +/** + * Represent a compressed object, with everything needed to decompress it. + * @constructor + * @param {number} compressedSize the size of the data compressed. + * @param {number} uncompressedSize the size of the data after decompression. + * @param {number} crc32 the crc32 of the decompressed file. + * @param {object} compression the type of compression, see lib/compressions.js. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data. + */ +function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) { + this.compressedSize = compressedSize; + this.uncompressedSize = uncompressedSize; + this.crc32 = crc32; + this.compression = compression; + this.compressedContent = data; +} + +CompressedObject.prototype = { + /** + * Create a worker to get the uncompressed content. + * @return {GenericWorker} the worker. + */ + getContentWorker : function () { + var worker = new DataWorker(external.Promise.resolve(this.compressedContent)) + .pipe(this.compression.uncompressWorker()) + .pipe(new DataLengthProbe("data_length")); + + var that = this; + worker.on("end", function () { + if(this.streamInfo['data_length'] !== that.uncompressedSize) { + throw new Error("Bug : uncompressed data size mismatch"); + } + }); + return worker; + }, + /** + * Create a worker to get the compressed content. + * @return {GenericWorker} the worker. + */ + getCompressedWorker : function () { + return new DataWorker(external.Promise.resolve(this.compressedContent)) + .withStreamInfo("compressedSize", this.compressedSize) + .withStreamInfo("uncompressedSize", this.uncompressedSize) + .withStreamInfo("crc32", this.crc32) + .withStreamInfo("compression", this.compression) + ; + } +}; + +/** + * Chain the given worker with other workers to compress the content with the + * given compresion. + * @param {GenericWorker} uncompressedWorker the worker to pipe. + * @param {Object} compression the compression object. + * @param {Object} compressionOptions the options to use when compressing. + * @return {GenericWorker} the new worker compressing the content. + */ +CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions) { + return uncompressedWorker + .pipe(new Crc32Probe()) + .pipe(new DataLengthProbe("uncompressedSize")) + .pipe(compression.compressWorker(compressionOptions)) + .pipe(new DataLengthProbe("compressedSize")) + .withStreamInfo("compression", compression); +}; + +module.exports = CompressedObject; + +},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require("./stream/GenericWorker"); + +exports.STORE = { + magic: "\x00\x00", + compressWorker : function (compressionOptions) { + return new GenericWorker("STORE compression"); + }, + uncompressWorker : function () { + return new GenericWorker("STORE decompression"); + } +}; +exports.DEFLATE = require('./flate'); + +},{"./flate":7,"./stream/GenericWorker":28}],4:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); + +/** + * The following functions come from pako, from pako/lib/zlib/crc32.js + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +// That's all for the pako functions. + +/** + * Compute the crc32 of a string. + * This is almost the same as the function crc32, but for strings. Using the + * same function for the two use cases leads to horrible performances. + * @param {Number} crc the starting value of the crc. + * @param {String} str the string to use. + * @param {Number} len the length of the string. + * @param {Number} pos the starting position for the crc32 computation. + * @return {Number} the computed crc32. + */ +function crc32str(crc, str, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +module.exports = function crc32wrapper(input, crc) { + if (typeof input === "undefined" || !input.length) { + return 0; + } + + var isArray = utils.getTypeOf(input) !== "string"; + + if(isArray) { + return crc32(crc|0, input, input.length, 0); + } else { + return crc32str(crc|0, input, input.length, 0); + } +}; + +},{"./utils":32}],5:[function(require,module,exports){ +'use strict'; +exports.base64 = false; +exports.binary = false; +exports.dir = false; +exports.createFolders = true; +exports.date = null; +exports.compression = null; +exports.compressionOptions = null; +exports.comment = null; +exports.unixPermissions = null; +exports.dosPermissions = null; + +},{}],6:[function(require,module,exports){ +/* global Promise */ +'use strict'; + +// load the global object first: +// - it should be better integrated in the system (unhandledRejection in node) +// - the environment may have a custom Promise implementation (see zone.js) +var ES6Promise = null; +if (typeof Promise !== "undefined") { + ES6Promise = Promise; +} else { + ES6Promise = require("lie"); +} + +/** + * Let the user use/change some implementations. + */ +module.exports = { + Promise: ES6Promise +}; + +},{"lie":58}],7:[function(require,module,exports){ +'use strict'; +var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); + +var pako = require("pako"); +var utils = require("./utils"); +var GenericWorker = require("./stream/GenericWorker"); + +var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array"; + +exports.magic = "\x08\x00"; + +/** + * Create a worker that uses pako to inflate/deflate. + * @constructor + * @param {String} action the name of the pako function to call : either "Deflate" or "Inflate". + * @param {Object} options the options to use when (de)compressing. + */ +function FlateWorker(action, options) { + GenericWorker.call(this, "FlateWorker/" + action); + + this._pako = null; + this._pakoAction = action; + this._pakoOptions = options; + // the `meta` object from the last chunk received + // this allow this worker to pass around metadata + this.meta = {}; +} + +utils.inherits(FlateWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +FlateWorker.prototype.processChunk = function (chunk) { + this.meta = chunk.meta; + if (this._pako === null) { + this._createPako(); + } + this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false); +}; + +/** + * @see GenericWorker.flush + */ +FlateWorker.prototype.flush = function () { + GenericWorker.prototype.flush.call(this); + if (this._pako === null) { + this._createPako(); + } + this._pako.push([], true); +}; +/** + * @see GenericWorker.cleanUp + */ +FlateWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this._pako = null; +}; + +/** + * Create the _pako object. + * TODO: lazy-loading this object isn't the best solution but it's the + * quickest. The best solution is to lazy-load the worker list. See also the + * issue #446. + */ +FlateWorker.prototype._createPako = function () { + this._pako = new pako[this._pakoAction]({ + raw: true, + level: this._pakoOptions.level || -1 // default compression + }); + var self = this; + this._pako.onData = function(data) { + self.push({ + data : data, + meta : self.meta + }); + }; +}; + +exports.compressWorker = function (compressionOptions) { + return new FlateWorker("Deflate", compressionOptions); +}; +exports.uncompressWorker = function () { + return new FlateWorker("Inflate", {}); +}; + +},{"./stream/GenericWorker":28,"./utils":32,"pako":59}],8:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); +var utf8 = require('../utf8'); +var crc32 = require('../crc32'); +var signature = require('../signature'); + +/** + * Transform an integer into a string in hexadecimal. + * @private + * @param {number} dec the number to convert. + * @param {number} bytes the number of bytes to generate. + * @returns {string} the result. + */ +var decToHex = function(dec, bytes) { + var hex = "", i; + for (i = 0; i < bytes; i++) { + hex += String.fromCharCode(dec & 0xff); + dec = dec >>> 8; + } + return hex; +}; + +/** + * Generate the UNIX part of the external file attributes. + * @param {Object} unixPermissions the unix permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : + * + * TTTTsstrwxrwxrwx0000000000ADVSHR + * ^^^^____________________________ file type, see zipinfo.c (UNX_*) + * ^^^_________________________ setuid, setgid, sticky + * ^^^^^^^^^________________ permissions + * ^^^^^^^^^^______ not used ? + * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only + */ +var generateUnixExternalFileAttr = function (unixPermissions, isDir) { + + var result = unixPermissions; + if (!unixPermissions) { + // I can't use octal values in strict mode, hence the hexa. + // 040775 => 0x41fd + // 0100664 => 0x81b4 + result = isDir ? 0x41fd : 0x81b4; + } + return (result & 0xFFFF) << 16; +}; + +/** + * Generate the DOS part of the external file attributes. + * @param {Object} dosPermissions the dos permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * Bit 0 Read-Only + * Bit 1 Hidden + * Bit 2 System + * Bit 3 Volume Label + * Bit 4 Directory + * Bit 5 Archive + */ +var generateDosExternalFileAttr = function (dosPermissions, isDir) { + + // the dir flag is already set for compatibility + return (dosPermissions || 0) & 0x3F; +}; + +/** + * Generate the various parts used in the construction of the final zip file. + * @param {Object} streamInfo the hash with informations about the compressed file. + * @param {Boolean} streamedContent is the content streamed ? + * @param {Boolean} streamingEnded is the stream finished ? + * @param {number} offset the current offset from the start of the zip file. + * @param {String} platform let's pretend we are this platform (change platform dependents fields) + * @param {Function} encodeFileName the function to encode the file name / comment. + * @return {Object} the zip parts. + */ +var generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) { + var file = streamInfo['file'], + compression = streamInfo['compression'], + useCustomEncoding = encodeFileName !== utf8.utf8encode, + encodedFileName = utils.transformTo("string", encodeFileName(file.name)), + utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), + comment = file.comment, + encodedComment = utils.transformTo("string", encodeFileName(comment)), + utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), + useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, + useUTF8ForComment = utfEncodedComment.length !== comment.length, + dosTime, + dosDate, + extraFields = "", + unicodePathExtraField = "", + unicodeCommentExtraField = "", + dir = file.dir, + date = file.date; + + + var dataInfo = { + crc32 : 0, + compressedSize : 0, + uncompressedSize : 0 + }; + + // if the content is streamed, the sizes/crc32 are only available AFTER + // the end of the stream. + if (!streamedContent || streamingEnded) { + dataInfo.crc32 = streamInfo['crc32']; + dataInfo.compressedSize = streamInfo['compressedSize']; + dataInfo.uncompressedSize = streamInfo['uncompressedSize']; + } + + var bitflag = 0; + if (streamedContent) { + // Bit 3: the sizes/crc32 are set to zero in the local header. + // The correct values are put in the data descriptor immediately + // following the compressed data. + bitflag |= 0x0008; + } + if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) { + // Bit 11: Language encoding flag (EFS). + bitflag |= 0x0800; + } + + + var extFileAttr = 0; + var versionMadeBy = 0; + if (dir) { + // dos or unix, we set the dos dir flag + extFileAttr |= 0x00010; + } + if(platform === "UNIX") { + versionMadeBy = 0x031E; // UNIX, version 3.0 + extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); + } else { // DOS or other, fallback to DOS + versionMadeBy = 0x0014; // DOS, version 2.0 + extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); + } + + // date + // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html + + dosTime = date.getUTCHours(); + dosTime = dosTime << 6; + dosTime = dosTime | date.getUTCMinutes(); + dosTime = dosTime << 5; + dosTime = dosTime | date.getUTCSeconds() / 2; + + dosDate = date.getUTCFullYear() - 1980; + dosDate = dosDate << 4; + dosDate = dosDate | (date.getUTCMonth() + 1); + dosDate = dosDate << 5; + dosDate = dosDate | date.getUTCDate(); + + if (useUTF8ForFileName) { + // set the unicode path extra field. unzip needs at least one extra + // field to correctly handle unicode path, so using the path is as good + // as any other information. This could improve the situation with + // other archive managers too. + // This field is usually used without the utf8 flag, with a non + // unicode path in the header (winrar, winzip). This helps (a bit) + // with the messy Windows' default compressed folders feature but + // breaks on p7zip which doesn't seek the unicode path extra field. + // So for now, UTF-8 everywhere ! + unicodePathExtraField = + // Version + decToHex(1, 1) + + // NameCRC32 + decToHex(crc32(encodedFileName), 4) + + // UnicodeName + utfEncodedFileName; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x70" + + // size + decToHex(unicodePathExtraField.length, 2) + + // content + unicodePathExtraField; + } + + if(useUTF8ForComment) { + + unicodeCommentExtraField = + // Version + decToHex(1, 1) + + // CommentCRC32 + decToHex(crc32(encodedComment), 4) + + // UnicodeName + utfEncodedComment; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x63" + + // size + decToHex(unicodeCommentExtraField.length, 2) + + // content + unicodeCommentExtraField; + } + + var header = ""; + + // version needed to extract + header += "\x0A\x00"; + // general purpose bit flag + header += decToHex(bitflag, 2); + // compression method + header += compression.magic; + // last mod file time + header += decToHex(dosTime, 2); + // last mod file date + header += decToHex(dosDate, 2); + // crc-32 + header += decToHex(dataInfo.crc32, 4); + // compressed size + header += decToHex(dataInfo.compressedSize, 4); + // uncompressed size + header += decToHex(dataInfo.uncompressedSize, 4); + // file name length + header += decToHex(encodedFileName.length, 2); + // extra field length + header += decToHex(extraFields.length, 2); + + + var fileRecord = signature.LOCAL_FILE_HEADER + header + encodedFileName + extraFields; + + var dirRecord = signature.CENTRAL_FILE_HEADER + + // version made by (00: DOS) + decToHex(versionMadeBy, 2) + + // file header (common to file and central directory) + header + + // file comment length + decToHex(encodedComment.length, 2) + + // disk number start + "\x00\x00" + + // internal file attributes TODO + "\x00\x00" + + // external file attributes + decToHex(extFileAttr, 4) + + // relative offset of local header + decToHex(offset, 4) + + // file name + encodedFileName + + // extra field + extraFields + + // file comment + encodedComment; + + return { + fileRecord: fileRecord, + dirRecord: dirRecord + }; +}; + +/** + * Generate the EOCD record. + * @param {Number} entriesCount the number of entries in the zip file. + * @param {Number} centralDirLength the length (in bytes) of the central dir. + * @param {Number} localDirLength the length (in bytes) of the local dir. + * @param {String} comment the zip file comment as a binary string. + * @param {Function} encodeFileName the function to encode the comment. + * @return {String} the EOCD record. + */ +var generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) { + var dirEnd = ""; + var encodedComment = utils.transformTo("string", encodeFileName(comment)); + + // end of central dir signature + dirEnd = signature.CENTRAL_DIRECTORY_END + + // number of this disk + "\x00\x00" + + // number of the disk with the start of the central directory + "\x00\x00" + + // total number of entries in the central directory on this disk + decToHex(entriesCount, 2) + + // total number of entries in the central directory + decToHex(entriesCount, 2) + + // size of the central directory 4 bytes + decToHex(centralDirLength, 4) + + // offset of start of central directory with respect to the starting disk number + decToHex(localDirLength, 4) + + // .ZIP file comment length + decToHex(encodedComment.length, 2) + + // .ZIP file comment + encodedComment; + + return dirEnd; +}; + +/** + * Generate data descriptors for a file entry. + * @param {Object} streamInfo the hash generated by a worker, containing informations + * on the file entry. + * @return {String} the data descriptors. + */ +var generateDataDescriptors = function (streamInfo) { + var descriptor = ""; + descriptor = signature.DATA_DESCRIPTOR + + // crc-32 4 bytes + decToHex(streamInfo['crc32'], 4) + + // compressed size 4 bytes + decToHex(streamInfo['compressedSize'], 4) + + // uncompressed size 4 bytes + decToHex(streamInfo['uncompressedSize'], 4); + + return descriptor; +}; + + +/** + * A worker to concatenate other workers to create a zip file. + * @param {Boolean} streamFiles `true` to stream the content of the files, + * `false` to accumulate it. + * @param {String} comment the comment to use. + * @param {String} platform the platform to use, "UNIX" or "DOS". + * @param {Function} encodeFileName the function to encode file names and comments. + */ +function ZipFileWorker(streamFiles, comment, platform, encodeFileName) { + GenericWorker.call(this, "ZipFileWorker"); + // The number of bytes written so far. This doesn't count accumulated chunks. + this.bytesWritten = 0; + // The comment of the zip file + this.zipComment = comment; + // The platform "generating" the zip file. + this.zipPlatform = platform; + // the function to encode file names and comments. + this.encodeFileName = encodeFileName; + // Should we stream the content of the files ? + this.streamFiles = streamFiles; + // If `streamFiles` is false, we will need to accumulate the content of the + // files to calculate sizes / crc32 (and write them *before* the content). + // This boolean indicates if we are accumulating chunks (it will change a lot + // during the lifetime of this worker). + this.accumulate = false; + // The buffer receiving chunks when accumulating content. + this.contentBuffer = []; + // The list of generated directory records. + this.dirRecords = []; + // The offset (in bytes) from the beginning of the zip file for the current source. + this.currentSourceOffset = 0; + // The total number of entries in this zip file. + this.entriesCount = 0; + // the name of the file currently being added, null when handling the end of the zip file. + // Used for the emited metadata. + this.currentFile = null; + + + + this._sources = []; +} +utils.inherits(ZipFileWorker, GenericWorker); + +/** + * @see GenericWorker.push + */ +ZipFileWorker.prototype.push = function (chunk) { + + var currentFilePercent = chunk.meta.percent || 0; + var entriesCount = this.entriesCount; + var remainingFiles = this._sources.length; + + if(this.accumulate) { + this.contentBuffer.push(chunk); + } else { + this.bytesWritten += chunk.data.length; + + GenericWorker.prototype.push.call(this, { + data : chunk.data, + meta : { + currentFile : this.currentFile, + percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100 + } + }); + } +}; + +/** + * The worker started a new source (an other worker). + * @param {Object} streamInfo the streamInfo object from the new source. + */ +ZipFileWorker.prototype.openedSource = function (streamInfo) { + this.currentSourceOffset = this.bytesWritten; + this.currentFile = streamInfo['file'].name; + + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + + // don't stream folders (because they don't have any content) + if(streamedContent) { + var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + } else { + // we need to wait for the whole file before pushing anything + this.accumulate = true; + } +}; + +/** + * The worker finished a source (an other worker). + * @param {Object} streamInfo the streamInfo object from the finished source. + */ +ZipFileWorker.prototype.closedSource = function (streamInfo) { + this.accumulate = false; + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + + this.dirRecords.push(record.dirRecord); + if(streamedContent) { + // after the streamed file, we put data descriptors + this.push({ + data : generateDataDescriptors(streamInfo), + meta : {percent:100} + }); + } else { + // the content wasn't streamed, we need to push everything now + // first the file record, then the content + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + while(this.contentBuffer.length) { + this.push(this.contentBuffer.shift()); + } + } + this.currentFile = null; +}; + +/** + * @see GenericWorker.flush + */ +ZipFileWorker.prototype.flush = function () { + + var localDirLength = this.bytesWritten; + for(var i = 0; i < this.dirRecords.length; i++) { + this.push({ + data : this.dirRecords[i], + meta : {percent:100} + }); + } + var centralDirLength = this.bytesWritten - localDirLength; + + var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName); + + this.push({ + data : dirEnd, + meta : {percent:100} + }); +}; + +/** + * Prepare the next source to be read. + */ +ZipFileWorker.prototype.prepareNextSource = function () { + this.previous = this._sources.shift(); + this.openedSource(this.previous.streamInfo); + if (this.isPaused) { + this.previous.pause(); + } else { + this.previous.resume(); + } +}; + +/** + * @see GenericWorker.registerPrevious + */ +ZipFileWorker.prototype.registerPrevious = function (previous) { + this._sources.push(previous); + var self = this; + + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.closedSource(self.previous.streamInfo); + if(self._sources.length) { + self.prepareNextSource(); + } else { + self.end(); + } + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; +}; + +/** + * @see GenericWorker.resume + */ +ZipFileWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this.previous && this._sources.length) { + this.prepareNextSource(); + return true; + } + if (!this.previous && !this._sources.length && !this.generatedError) { + this.end(); + return true; + } +}; + +/** + * @see GenericWorker.error + */ +ZipFileWorker.prototype.error = function (e) { + var sources = this._sources; + if(!GenericWorker.prototype.error.call(this, e)) { + return false; + } + for(var i = 0; i < sources.length; i++) { + try { + sources[i].error(e); + } catch(e) { + // the `error` exploded, nothing to do + } + } + return true; +}; + +/** + * @see GenericWorker.lock + */ +ZipFileWorker.prototype.lock = function () { + GenericWorker.prototype.lock.call(this); + var sources = this._sources; + for(var i = 0; i < sources.length; i++) { + sources[i].lock(); + } +}; + +module.exports = ZipFileWorker; + +},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(require,module,exports){ +'use strict'; + +var compressions = require('../compressions'); +var ZipFileWorker = require('./ZipFileWorker'); + +/** + * Find the compression to use. + * @param {String} fileCompression the compression defined at the file level, if any. + * @param {String} zipCompression the compression defined at the load() level. + * @return {Object} the compression object to use. + */ +var getCompression = function (fileCompression, zipCompression) { + + var compressionName = fileCompression || zipCompression; + var compression = compressions[compressionName]; + if (!compression) { + throw new Error(compressionName + " is not a valid compression method !"); + } + return compression; +}; + +/** + * Create a worker to generate a zip file. + * @param {JSZip} zip the JSZip instance at the right root level. + * @param {Object} options to generate the zip file. + * @param {String} comment the comment to use. + */ +exports.generateWorker = function (zip, options, comment) { + + var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName); + var entriesCount = 0; + try { + + zip.forEach(function (relativePath, file) { + entriesCount++; + var compression = getCompression(file.options.compression, options.compression); + var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; + var dir = file.dir, date = file.date; + + file._compressWorker(compression, compressionOptions) + .withStreamInfo("file", { + name : relativePath, + dir : dir, + date : date, + comment : file.comment || "", + unixPermissions : file.unixPermissions, + dosPermissions : file.dosPermissions + }) + .pipe(zipFileWorker); + }); + zipFileWorker.entriesCount = entriesCount; + } catch (e) { + zipFileWorker.error(e); + } + + return zipFileWorker; +}; + +},{"../compressions":3,"./ZipFileWorker":8}],10:[function(require,module,exports){ +'use strict'; + +/** + * Representation a of zip file in js + * @constructor + */ +function JSZip() { + // if this constructor is used without `new`, it adds `new` before itself: + if(!(this instanceof JSZip)) { + return new JSZip(); + } + + if(arguments.length) { + throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); + } + + // object containing the files : + // { + // "folder/" : {...}, + // "folder/data.txt" : {...} + // } + this.files = {}; + + this.comment = null; + + // Where we are in the hierarchy + this.root = ""; + this.clone = function() { + var newObj = new JSZip(); + for (var i in this) { + if (typeof this[i] !== "function") { + newObj[i] = this[i]; + } + } + return newObj; + }; +} +JSZip.prototype = require('./object'); +JSZip.prototype.loadAsync = require('./load'); +JSZip.support = require('./support'); +JSZip.defaults = require('./defaults'); + +// TODO find a better way to handle this version, +// a require('package.json').version doesn't work with webpack, see #327 +JSZip.version = "3.1.5"; + +JSZip.loadAsync = function (content, options) { + return new JSZip().loadAsync(content, options); +}; + +JSZip.external = require("./external"); +module.exports = JSZip; + +},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(require,module,exports){ +'use strict'; +var utils = require('./utils'); +var external = require("./external"); +var utf8 = require('./utf8'); +var utils = require('./utils'); +var ZipEntries = require('./zipEntries'); +var Crc32Probe = require('./stream/Crc32Probe'); +var nodejsUtils = require("./nodejsUtils"); + +/** + * Check the CRC32 of an entry. + * @param {ZipEntry} zipEntry the zip entry to check. + * @return {Promise} the result. + */ +function checkEntryCRC32(zipEntry) { + return new external.Promise(function (resolve, reject) { + var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe()); + worker.on("error", function (e) { + reject(e); + }) + .on("end", function () { + if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) { + reject(new Error("Corrupted zip : CRC32 mismatch")); + } else { + resolve(); + } + }) + .resume(); + }); +} + +module.exports = function(data, options) { + var zip = this; + options = utils.extend(options || {}, { + base64: false, + checkCRC32: false, + optimizedBinaryString: false, + createFolders: false, + decodeFileName: utf8.utf8decode + }); + + if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + return external.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")); + } + + return utils.prepareContent("the loaded zip file", data, true, options.optimizedBinaryString, options.base64) + .then(function(data) { + var zipEntries = new ZipEntries(options); + zipEntries.load(data); + return zipEntries; + }).then(function checkCRC32(zipEntries) { + var promises = [external.Promise.resolve(zipEntries)]; + var files = zipEntries.files; + if (options.checkCRC32) { + for (var i = 0; i < files.length; i++) { + promises.push(checkEntryCRC32(files[i])); + } + } + return external.Promise.all(promises); + }).then(function addFiles(results) { + var zipEntries = results.shift(); + var files = zipEntries.files; + for (var i = 0; i < files.length; i++) { + var input = files[i]; + zip.file(input.fileNameStr, input.decompressed, { + binary: true, + optimizedBinaryString: true, + date: input.date, + dir: input.dir, + comment : input.fileCommentStr.length ? input.fileCommentStr : null, + unixPermissions : input.unixPermissions, + dosPermissions : input.dosPermissions, + createFolders: options.createFolders + }); + } + if (zipEntries.zipComment.length) { + zip.comment = zipEntries.zipComment; + } + + return zip; + }); +}; + +},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(require,module,exports){ +"use strict"; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); + +/** + * A worker that use a nodejs stream as source. + * @constructor + * @param {String} filename the name of the file entry for this stream. + * @param {Readable} stream the nodejs stream. + */ +function NodejsStreamInputAdapter(filename, stream) { + GenericWorker.call(this, "Nodejs stream input adapter for " + filename); + this._upstreamEnded = false; + this._bindStream(stream); +} + +utils.inherits(NodejsStreamInputAdapter, GenericWorker); + +/** + * Prepare the stream and bind the callbacks on it. + * Do this ASAP on node 0.10 ! A lazy binding doesn't always work. + * @param {Stream} stream the nodejs stream to use. + */ +NodejsStreamInputAdapter.prototype._bindStream = function (stream) { + var self = this; + this._stream = stream; + stream.pause(); + stream + .on("data", function (chunk) { + self.push({ + data: chunk, + meta : { + percent : 0 + } + }); + }) + .on("error", function (e) { + if(self.isPaused) { + this.generatedError = e; + } else { + self.error(e); + } + }) + .on("end", function () { + if(self.isPaused) { + self._upstreamEnded = true; + } else { + self.end(); + } + }); +}; +NodejsStreamInputAdapter.prototype.pause = function () { + if(!GenericWorker.prototype.pause.call(this)) { + return false; + } + this._stream.pause(); + return true; +}; +NodejsStreamInputAdapter.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if(this._upstreamEnded) { + this.end(); + } else { + this._stream.resume(); + } + + return true; +}; + +module.exports = NodejsStreamInputAdapter; + +},{"../stream/GenericWorker":28,"../utils":32}],13:[function(require,module,exports){ +'use strict'; + +var Readable = require('readable-stream').Readable; + +var utils = require('../utils'); +utils.inherits(NodejsStreamOutputAdapter, Readable); + +/** +* A nodejs stream using a worker as source. +* @see the SourceWrapper in http://nodejs.org/api/stream.html +* @constructor +* @param {StreamHelper} helper the helper wrapping the worker +* @param {Object} options the nodejs stream options +* @param {Function} updateCb the update callback. +*/ +function NodejsStreamOutputAdapter(helper, options, updateCb) { + Readable.call(this, options); + this._helper = helper; + + var self = this; + helper.on("data", function (data, meta) { + if (!self.push(data)) { + self._helper.pause(); + } + if(updateCb) { + updateCb(meta); + } + }) + .on("error", function(e) { + self.emit('error', e); + }) + .on("end", function () { + self.push(null); + }); +} + + +NodejsStreamOutputAdapter.prototype._read = function() { + this._helper.resume(); +}; + +module.exports = NodejsStreamOutputAdapter; + +},{"../utils":32,"readable-stream":16}],14:[function(require,module,exports){ +'use strict'; + +module.exports = { + /** + * True if this is running in Nodejs, will be undefined in a browser. + * In a browser, browserify won't include this file and the whole module + * will be resolved an empty object. + */ + isNode : typeof Buffer !== "undefined", + /** + * Create a new nodejs Buffer from an existing content. + * @param {Object} data the data to pass to the constructor. + * @param {String} encoding the encoding to use. + * @return {Buffer} a new Buffer. + */ + newBufferFrom: function(data, encoding) { + // XXX We can't use `Buffer.from` which comes from `Uint8Array.from` + // in nodejs v4 (< v.4.5). It's not the expected implementation (and + // has a different signature). + // see https://github.com/nodejs/node/issues/8053 + // A condition on nodejs' version won't solve the issue as we don't + // control the Buffer polyfills that may or may not be used. + return new Buffer(data, encoding); + }, + /** + * Create a new nodejs Buffer with the specified size. + * @param {Integer} size the size of the buffer. + * @return {Buffer} a new Buffer. + */ + allocBuffer: function (size) { + if (Buffer.alloc) { + return Buffer.alloc(size); + } else { + return new Buffer(size); + } + }, + /** + * Find out if an object is a Buffer. + * @param {Object} b the object to test. + * @return {Boolean} true if the object is a Buffer, false otherwise. + */ + isBuffer : function(b){ + return Buffer.isBuffer(b); + }, + + isStream : function (obj) { + return obj && + typeof obj.on === "function" && + typeof obj.pause === "function" && + typeof obj.resume === "function"; + } +}; + +},{}],15:[function(require,module,exports){ +'use strict'; +var utf8 = require('./utf8'); +var utils = require('./utils'); +var GenericWorker = require('./stream/GenericWorker'); +var StreamHelper = require('./stream/StreamHelper'); +var defaults = require('./defaults'); +var CompressedObject = require('./compressedObject'); +var ZipObject = require('./zipObject'); +var generate = require("./generate"); +var nodejsUtils = require("./nodejsUtils"); +var NodejsStreamInputAdapter = require("./nodejs/NodejsStreamInputAdapter"); + + +/** + * Add a file in the current folder. + * @private + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file + * @param {Object} originalOptions the options of the file + * @return {Object} the new file. + */ +var fileAdd = function(name, data, originalOptions) { + // be sure sub folders exist + var dataType = utils.getTypeOf(data), + parent; + + + /* + * Correct options. + */ + + var o = utils.extend(originalOptions || {}, defaults); + o.date = o.date || new Date(); + if (o.compression !== null) { + o.compression = o.compression.toUpperCase(); + } + + if (typeof o.unixPermissions === "string") { + o.unixPermissions = parseInt(o.unixPermissions, 8); + } + + // UNX_IFDIR 0040000 see zipinfo.c + if (o.unixPermissions && (o.unixPermissions & 0x4000)) { + o.dir = true; + } + // Bit 4 Directory + if (o.dosPermissions && (o.dosPermissions & 0x0010)) { + o.dir = true; + } + + if (o.dir) { + name = forceTrailingSlash(name); + } + if (o.createFolders && (parent = parentFolder(name))) { + folderAdd.call(this, parent, true); + } + + var isUnicodeString = dataType === "string" && o.binary === false && o.base64 === false; + if (!originalOptions || typeof originalOptions.binary === "undefined") { + o.binary = !isUnicodeString; + } + + + var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0; + + if (isCompressedEmpty || o.dir || !data || data.length === 0) { + o.base64 = false; + o.binary = true; + data = ""; + o.compression = "STORE"; + dataType = "string"; + } + + /* + * Convert content to fit. + */ + + var zipObjectContent = null; + if (data instanceof CompressedObject || data instanceof GenericWorker) { + zipObjectContent = data; + } else if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + zipObjectContent = new NodejsStreamInputAdapter(name, data); + } else { + zipObjectContent = utils.prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64); + } + + var object = new ZipObject(name, zipObjectContent, o); + this.files[name] = object; + /* + TODO: we can't throw an exception because we have async promises + (we can have a promise of a Date() for example) but returning a + promise is useless because file(name, data) returns the JSZip + object for chaining. Should we break that to allow the user + to catch the error ? + + return external.Promise.resolve(zipObjectContent) + .then(function () { + return object; + }); + */ +}; + +/** + * Find the parent folder of the path. + * @private + * @param {string} path the path to use + * @return {string} the parent folder, or "" + */ +var parentFolder = function (path) { + if (path.slice(-1) === '/') { + path = path.substring(0, path.length - 1); + } + var lastSlash = path.lastIndexOf('/'); + return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; +}; + +/** + * Returns the path with a slash at the end. + * @private + * @param {String} path the path to check. + * @return {String} the path with a trailing slash. + */ +var forceTrailingSlash = function(path) { + // Check the name ends with a / + if (path.slice(-1) !== "/") { + path += "/"; // IE doesn't like substr(-1) + } + return path; +}; + +/** + * Add a (sub) folder in the current folder. + * @private + * @param {string} name the folder's name + * @param {boolean=} [createFolders] If true, automatically create sub + * folders. Defaults to false. + * @return {Object} the new folder. + */ +var folderAdd = function(name, createFolders) { + createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders; + + name = forceTrailingSlash(name); + + // Does this folder already exist? + if (!this.files[name]) { + fileAdd.call(this, name, null, { + dir: true, + createFolders: createFolders + }); + } + return this.files[name]; +}; + +/** +* Cross-window, cross-Node-context regular expression detection +* @param {Object} object Anything +* @return {Boolean} true if the object is a regular expression, +* false otherwise +*/ +function isRegExp(object) { + return Object.prototype.toString.call(object) === "[object RegExp]"; +} + +// return the actual prototype of JSZip +var out = { + /** + * @see loadAsync + */ + load: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + + /** + * Call a callback function for each entry at this folder level. + * @param {Function} cb the callback function: + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + */ + forEach: function(cb) { + var filename, relativePath, file; + for (filename in this.files) { + if (!this.files.hasOwnProperty(filename)) { + continue; + } + file = this.files[filename]; + relativePath = filename.slice(this.root.length, filename.length); + if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root + cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn... + } + } + }, + + /** + * Filter nested files/folders with the specified function. + * @param {Function} search the predicate to use : + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + * @return {Array} An array of matching elements. + */ + filter: function(search) { + var result = []; + this.forEach(function (relativePath, entry) { + if (search(relativePath, entry)) { // the file matches the function + result.push(entry); + } + + }); + return result; + }, + + /** + * Add a file to the zip file, or search a file. + * @param {string|RegExp} name The name of the file to add (if data is defined), + * the name of the file to find (if no data) or a regex to match files. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded + * @param {Object} o File options + * @return {JSZip|Object|Array} this JSZip object (when adding a file), + * a file (when searching by string) or an array of files (when searching by regex). + */ + file: function(name, data, o) { + if (arguments.length === 1) { + if (isRegExp(name)) { + var regexp = name; + return this.filter(function(relativePath, file) { + return !file.dir && regexp.test(relativePath); + }); + } + else { // text + var obj = this.files[this.root + name]; + if (obj && !obj.dir) { + return obj; + } else { + return null; + } + } + } + else { // more than one argument : we have data ! + name = this.root + name; + fileAdd.call(this, name, data, o); + } + return this; + }, + + /** + * Add a directory to the zip file, or search. + * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. + * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. + */ + folder: function(arg) { + if (!arg) { + return this; + } + + if (isRegExp(arg)) { + return this.filter(function(relativePath, file) { + return file.dir && arg.test(relativePath); + }); + } + + // else, name is a new folder + var name = this.root + arg; + var newFolder = folderAdd.call(this, name); + + // Allow chaining by returning a new object with this folder as the root + var ret = this.clone(); + ret.root = newFolder.name; + return ret; + }, + + /** + * Delete a file, or a directory and all sub-files, from the zip + * @param {string} name the name of the file to delete + * @return {JSZip} this JSZip object + */ + remove: function(name) { + name = this.root + name; + var file = this.files[name]; + if (!file) { + // Look for any folders + if (name.slice(-1) !== "/") { + name += "/"; + } + file = this.files[name]; + } + + if (file && !file.dir) { + // file + delete this.files[name]; + } else { + // maybe a folder, delete recursively + var kids = this.filter(function(relativePath, file) { + return file.name.slice(0, name.length) === name; + }); + for (var i = 0; i < kids.length; i++) { + delete this.files[kids[i].name]; + } + } + + return this; + }, + + /** + * Generate the complete zip file + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file + */ + generate: function(options) { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + /** + * Generate the complete zip file as an internal stream. + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {StreamHelper} the streamed zip file. + */ + generateInternalStream: function(options) { + var worker, opts = {}; + try { + opts = utils.extend(options || {}, { + streamFiles: false, + compression: "STORE", + compressionOptions : null, + type: "", + platform: "DOS", + comment: null, + mimeType: 'application/zip', + encodeFileName: utf8.utf8encode + }); + + opts.type = opts.type.toLowerCase(); + opts.compression = opts.compression.toUpperCase(); + + // "binarystring" is prefered but the internals use "string". + if(opts.type === "binarystring") { + opts.type = "string"; + } + + if (!opts.type) { + throw new Error("No output type specified."); + } + + utils.checkSupport(opts.type); + + // accept nodejs `process.platform` + if( + opts.platform === 'darwin' || + opts.platform === 'freebsd' || + opts.platform === 'linux' || + opts.platform === 'sunos' + ) { + opts.platform = "UNIX"; + } + if (opts.platform === 'win32') { + opts.platform = "DOS"; + } + + var comment = opts.comment || this.comment || ""; + worker = generate.generateWorker(this, opts, comment); + } catch (e) { + worker = new GenericWorker("error"); + worker.error(e); + } + return new StreamHelper(worker, opts.type || "string", opts.mimeType); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateAsync: function(options, onUpdate) { + return this.generateInternalStream(options).accumulate(onUpdate); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateNodeStream: function(options, onUpdate) { + options = options || {}; + if (!options.type) { + options.type = "nodebuffer"; + } + return this.generateInternalStream(options).toNodejsStream(onUpdate); + } +}; +module.exports = out; + +},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(require,module,exports){ +/* + * This file is used by module bundlers (browserify/webpack/etc) when + * including a stream implementation. We use "readable-stream" to get a + * consistent behavior between nodejs versions but bundlers often have a shim + * for "stream". Using this shim greatly improve the compatibility and greatly + * reduce the final size of the bundle (only one stream implementation, not + * two). + */ +module.exports = require("stream"); + +},{"stream":undefined}],17:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function ArrayReader(data) { + DataReader.call(this, data); + for(var i = 0; i < this.data.length; i++) { + data[i] = data[i] & 0xFF; + } +} +utils.inherits(ArrayReader, DataReader); +/** + * @see DataReader.byteAt + */ +ArrayReader.prototype.byteAt = function(i) { + return this.data[this.zero + i]; +}; +/** + * @see DataReader.lastIndexOfSignature + */ +ArrayReader.prototype.lastIndexOfSignature = function(sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3); + for (var i = this.length - 4; i >= 0; --i) { + if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { + return i - this.zero; + } + } + + return -1; +}; +/** + * @see DataReader.readAndCheckSignature + */ +ArrayReader.prototype.readAndCheckSignature = function (sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3), + data = this.readData(4); + return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3]; +}; +/** + * @see DataReader.readData + */ +ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + return []; + } + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = ArrayReader; + +},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){ +'use strict'; +var utils = require('../utils'); + +function DataReader(data) { + this.data = data; // type : see implementation + this.length = data.length; + this.index = 0; + this.zero = 0; +} +DataReader.prototype = { + /** + * Check that the offset will not go too far. + * @param {string} offset the additional offset to check. + * @throws {Error} an Error if the offset is out of bounds. + */ + checkOffset: function(offset) { + this.checkIndex(this.index + offset); + }, + /** + * Check that the specified index will not be too far. + * @param {string} newIndex the index to check. + * @throws {Error} an Error if the index is out of bounds. + */ + checkIndex: function(newIndex) { + if (this.length < this.zero + newIndex || newIndex < 0) { + throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); + } + }, + /** + * Change the index. + * @param {number} newIndex The new index. + * @throws {Error} if the new index is out of the data. + */ + setIndex: function(newIndex) { + this.checkIndex(newIndex); + this.index = newIndex; + }, + /** + * Skip the next n bytes. + * @param {number} n the number of bytes to skip. + * @throws {Error} if the new index is out of the data. + */ + skip: function(n) { + this.setIndex(this.index + n); + }, + /** + * Get the byte at the specified index. + * @param {number} i the index to use. + * @return {number} a byte. + */ + byteAt: function(i) { + // see implementations + }, + /** + * Get the next number with a given byte size. + * @param {number} size the number of bytes to read. + * @return {number} the corresponding number. + */ + readInt: function(size) { + var result = 0, + i; + this.checkOffset(size); + for (i = this.index + size - 1; i >= this.index; i--) { + result = (result << 8) + this.byteAt(i); + } + this.index += size; + return result; + }, + /** + * Get the next string with a given byte size. + * @param {number} size the number of bytes to read. + * @return {string} the corresponding string. + */ + readString: function(size) { + return utils.transformTo("string", this.readData(size)); + }, + /** + * Get raw data without conversion, bytes. + * @param {number} size the number of bytes to read. + * @return {Object} the raw data, implementation specific. + */ + readData: function(size) { + // see implementations + }, + /** + * Find the last occurence of a zip signature (4 bytes). + * @param {string} sig the signature to find. + * @return {number} the index of the last occurence, -1 if not found. + */ + lastIndexOfSignature: function(sig) { + // see implementations + }, + /** + * Read the signature (4 bytes) at the current position and compare it with sig. + * @param {string} sig the expected signature + * @return {boolean} true if the signature matches, false otherwise. + */ + readAndCheckSignature: function(sig) { + // see implementations + }, + /** + * Get the next date. + * @return {Date} the date. + */ + readDate: function() { + var dostime = this.readInt(4); + return new Date(Date.UTC( + ((dostime >> 25) & 0x7f) + 1980, // year + ((dostime >> 21) & 0x0f) - 1, // month + (dostime >> 16) & 0x1f, // day + (dostime >> 11) & 0x1f, // hour + (dostime >> 5) & 0x3f, // minute + (dostime & 0x1f) << 1)); // second + } +}; +module.exports = DataReader; + +},{"../utils":32}],19:[function(require,module,exports){ +'use strict'; +var Uint8ArrayReader = require('./Uint8ArrayReader'); +var utils = require('../utils'); + +function NodeBufferReader(data) { + Uint8ArrayReader.call(this, data); +} +utils.inherits(NodeBufferReader, Uint8ArrayReader); + +/** + * @see DataReader.readData + */ +NodeBufferReader.prototype.readData = function(size) { + this.checkOffset(size); + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = NodeBufferReader; + +},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function StringReader(data) { + DataReader.call(this, data); +} +utils.inherits(StringReader, DataReader); +/** + * @see DataReader.byteAt + */ +StringReader.prototype.byteAt = function(i) { + return this.data.charCodeAt(this.zero + i); +}; +/** + * @see DataReader.lastIndexOfSignature + */ +StringReader.prototype.lastIndexOfSignature = function(sig) { + return this.data.lastIndexOf(sig) - this.zero; +}; +/** + * @see DataReader.readAndCheckSignature + */ +StringReader.prototype.readAndCheckSignature = function (sig) { + var data = this.readData(4); + return sig === data; +}; +/** + * @see DataReader.readData + */ +StringReader.prototype.readData = function(size) { + this.checkOffset(size); + // this will work because the constructor applied the "& 0xff" mask. + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = StringReader; + +},{"../utils":32,"./DataReader":18}],21:[function(require,module,exports){ +'use strict'; +var ArrayReader = require('./ArrayReader'); +var utils = require('../utils'); + +function Uint8ArrayReader(data) { + ArrayReader.call(this, data); +} +utils.inherits(Uint8ArrayReader, ArrayReader); +/** + * @see DataReader.readData + */ +Uint8ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. + return new Uint8Array(0); + } + var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = Uint8ArrayReader; + +},{"../utils":32,"./ArrayReader":17}],22:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var support = require('../support'); +var ArrayReader = require('./ArrayReader'); +var StringReader = require('./StringReader'); +var NodeBufferReader = require('./NodeBufferReader'); +var Uint8ArrayReader = require('./Uint8ArrayReader'); + +/** + * Create a reader adapted to the data. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read. + * @return {DataReader} the data reader. + */ +module.exports = function (data) { + var type = utils.getTypeOf(data); + utils.checkSupport(type); + if (type === "string" && !support.uint8array) { + return new StringReader(data); + } + if (type === "nodebuffer") { + return new NodeBufferReader(data); + } + if (support.uint8array) { + return new Uint8ArrayReader(utils.transformTo("uint8array", data)); + } + return new ArrayReader(utils.transformTo("array", data)); +}; + +},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(require,module,exports){ +'use strict'; +exports.LOCAL_FILE_HEADER = "PK\x03\x04"; +exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; +exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; +exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; +exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; +exports.DATA_DESCRIPTOR = "PK\x07\x08"; + +},{}],24:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var utils = require('../utils'); + +/** + * A worker which convert chunks to a specified type. + * @constructor + * @param {String} destType the destination type. + */ +function ConvertWorker(destType) { + GenericWorker.call(this, "ConvertWorker to " + destType); + this.destType = destType; +} +utils.inherits(ConvertWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +ConvertWorker.prototype.processChunk = function (chunk) { + this.push({ + data : utils.transformTo(this.destType, chunk.data), + meta : chunk.meta + }); +}; +module.exports = ConvertWorker; + +},{"../utils":32,"./GenericWorker":28}],25:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var crc32 = require('../crc32'); +var utils = require('../utils'); + +/** + * A worker which calculate the crc32 of the data flowing through. + * @constructor + */ +function Crc32Probe() { + GenericWorker.call(this, "Crc32Probe"); + this.withStreamInfo("crc32", 0); +} +utils.inherits(Crc32Probe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Crc32Probe.prototype.processChunk = function (chunk) { + this.streamInfo.crc32 = crc32(chunk.data, this.streamInfo.crc32 || 0); + this.push(chunk); +}; +module.exports = Crc32Probe; + +},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +/** + * A worker which calculate the total length of the data flowing through. + * @constructor + * @param {String} propName the name used to expose the length + */ +function DataLengthProbe(propName) { + GenericWorker.call(this, "DataLengthProbe for " + propName); + this.propName = propName; + this.withStreamInfo(propName, 0); +} +utils.inherits(DataLengthProbe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +DataLengthProbe.prototype.processChunk = function (chunk) { + if(chunk) { + var length = this.streamInfo[this.propName] || 0; + this.streamInfo[this.propName] = length + chunk.data.length; + } + GenericWorker.prototype.processChunk.call(this, chunk); +}; +module.exports = DataLengthProbe; + + +},{"../utils":32,"./GenericWorker":28}],27:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +// the size of the generated chunks +// TODO expose this as a public variable +var DEFAULT_BLOCK_SIZE = 16 * 1024; + +/** + * A worker that reads a content and emits chunks. + * @constructor + * @param {Promise} dataP the promise of the data to split + */ +function DataWorker(dataP) { + GenericWorker.call(this, "DataWorker"); + var self = this; + this.dataIsReady = false; + this.index = 0; + this.max = 0; + this.data = null; + this.type = ""; + + this._tickScheduled = false; + + dataP.then(function (data) { + self.dataIsReady = true; + self.data = data; + self.max = data && data.length || 0; + self.type = utils.getTypeOf(data); + if(!self.isPaused) { + self._tickAndRepeat(); + } + }, function (e) { + self.error(e); + }); +} + +utils.inherits(DataWorker, GenericWorker); + +/** + * @see GenericWorker.cleanUp + */ +DataWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this.data = null; +}; + +/** + * @see GenericWorker.resume + */ +DataWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this._tickScheduled && this.dataIsReady) { + this._tickScheduled = true; + utils.delay(this._tickAndRepeat, [], this); + } + return true; +}; + +/** + * Trigger a tick a schedule an other call to this function. + */ +DataWorker.prototype._tickAndRepeat = function() { + this._tickScheduled = false; + if(this.isPaused || this.isFinished) { + return; + } + this._tick(); + if(!this.isFinished) { + utils.delay(this._tickAndRepeat, [], this); + this._tickScheduled = true; + } +}; + +/** + * Read and push a chunk. + */ +DataWorker.prototype._tick = function() { + + if(this.isPaused || this.isFinished) { + return false; + } + + var size = DEFAULT_BLOCK_SIZE; + var data = null, nextIndex = Math.min(this.max, this.index + size); + if (this.index >= this.max) { + // EOF + return this.end(); + } else { + switch(this.type) { + case "string": + data = this.data.substring(this.index, nextIndex); + break; + case "uint8array": + data = this.data.subarray(this.index, nextIndex); + break; + case "array": + case "nodebuffer": + data = this.data.slice(this.index, nextIndex); + break; + } + this.index = nextIndex; + return this.push({ + data : data, + meta : { + percent : this.max ? this.index / this.max * 100 : 0 + } + }); + } +}; + +module.exports = DataWorker; + +},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){ +'use strict'; + +/** + * A worker that does nothing but passing chunks to the next one. This is like + * a nodejs stream but with some differences. On the good side : + * - it works on IE 6-9 without any issue / polyfill + * - it weights less than the full dependencies bundled with browserify + * - it forwards errors (no need to declare an error handler EVERYWHERE) + * + * A chunk is an object with 2 attributes : `meta` and `data`. The former is an + * object containing anything (`percent` for example), see each worker for more + * details. The latter is the real data (String, Uint8Array, etc). + * + * @constructor + * @param {String} name the name of the stream (mainly used for debugging purposes) + */ +function GenericWorker(name) { + // the name of the worker + this.name = name || "default"; + // an object containing metadata about the workers chain + this.streamInfo = {}; + // an error which happened when the worker was paused + this.generatedError = null; + // an object containing metadata to be merged by this worker into the general metadata + this.extraStreamInfo = {}; + // true if the stream is paused (and should not do anything), false otherwise + this.isPaused = true; + // true if the stream is finished (and should not do anything), false otherwise + this.isFinished = false; + // true if the stream is locked to prevent further structure updates (pipe), false otherwise + this.isLocked = false; + // the event listeners + this._listeners = { + 'data':[], + 'end':[], + 'error':[] + }; + // the previous worker, if any + this.previous = null; +} + +GenericWorker.prototype = { + /** + * Push a chunk to the next workers. + * @param {Object} chunk the chunk to push + */ + push : function (chunk) { + this.emit("data", chunk); + }, + /** + * End the stream. + * @return {Boolean} true if this call ended the worker, false otherwise. + */ + end : function () { + if (this.isFinished) { + return false; + } + + this.flush(); + try { + this.emit("end"); + this.cleanUp(); + this.isFinished = true; + } catch (e) { + this.emit("error", e); + } + return true; + }, + /** + * End the stream with an error. + * @param {Error} e the error which caused the premature end. + * @return {Boolean} true if this call ended the worker with an error, false otherwise. + */ + error : function (e) { + if (this.isFinished) { + return false; + } + + if(this.isPaused) { + this.generatedError = e; + } else { + this.isFinished = true; + + this.emit("error", e); + + // in the workers chain exploded in the middle of the chain, + // the error event will go downward but we also need to notify + // workers upward that there has been an error. + if(this.previous) { + this.previous.error(e); + } + + this.cleanUp(); + } + return true; + }, + /** + * Add a callback on an event. + * @param {String} name the name of the event (data, end, error) + * @param {Function} listener the function to call when the event is triggered + * @return {GenericWorker} the current object for chainability + */ + on : function (name, listener) { + this._listeners[name].push(listener); + return this; + }, + /** + * Clean any references when a worker is ending. + */ + cleanUp : function () { + this.streamInfo = this.generatedError = this.extraStreamInfo = null; + this._listeners = []; + }, + /** + * Trigger an event. This will call registered callback with the provided arg. + * @param {String} name the name of the event (data, end, error) + * @param {Object} arg the argument to call the callback with. + */ + emit : function (name, arg) { + if (this._listeners[name]) { + for(var i = 0; i < this._listeners[name].length; i++) { + this._listeners[name][i].call(this, arg); + } + } + }, + /** + * Chain a worker with an other. + * @param {Worker} next the worker receiving events from the current one. + * @return {worker} the next worker for chainability + */ + pipe : function (next) { + return next.registerPrevious(this); + }, + /** + * Same as `pipe` in the other direction. + * Using an API with `pipe(next)` is very easy. + * Implementing the API with the point of view of the next one registering + * a source is easier, see the ZipFileWorker. + * @param {Worker} previous the previous worker, sending events to this one + * @return {Worker} the current worker for chainability + */ + registerPrevious : function (previous) { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + + // sharing the streamInfo... + this.streamInfo = previous.streamInfo; + // ... and adding our own bits + this.mergeStreamInfo(); + this.previous = previous; + var self = this; + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.end(); + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; + }, + /** + * Pause the stream so it doesn't send events anymore. + * @return {Boolean} true if this call paused the worker, false otherwise. + */ + pause : function () { + if(this.isPaused || this.isFinished) { + return false; + } + this.isPaused = true; + + if(this.previous) { + this.previous.pause(); + } + return true; + }, + /** + * Resume a paused stream. + * @return {Boolean} true if this call resumed the worker, false otherwise. + */ + resume : function () { + if(!this.isPaused || this.isFinished) { + return false; + } + this.isPaused = false; + + // if true, the worker tried to resume but failed + var withError = false; + if(this.generatedError) { + this.error(this.generatedError); + withError = true; + } + if(this.previous) { + this.previous.resume(); + } + + return !withError; + }, + /** + * Flush any remaining bytes as the stream is ending. + */ + flush : function () {}, + /** + * Process a chunk. This is usually the method overridden. + * @param {Object} chunk the chunk to process. + */ + processChunk : function(chunk) { + this.push(chunk); + }, + /** + * Add a key/value to be added in the workers chain streamInfo once activated. + * @param {String} key the key to use + * @param {Object} value the associated value + * @return {Worker} the current worker for chainability + */ + withStreamInfo : function (key, value) { + this.extraStreamInfo[key] = value; + this.mergeStreamInfo(); + return this; + }, + /** + * Merge this worker's streamInfo into the chain's streamInfo. + */ + mergeStreamInfo : function () { + for(var key in this.extraStreamInfo) { + if (!this.extraStreamInfo.hasOwnProperty(key)) { + continue; + } + this.streamInfo[key] = this.extraStreamInfo[key]; + } + }, + + /** + * Lock the stream to prevent further updates on the workers chain. + * After calling this method, all calls to pipe will fail. + */ + lock: function () { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + this.isLocked = true; + if (this.previous) { + this.previous.lock(); + } + }, + + /** + * + * Pretty print the workers chain. + */ + toString : function () { + var me = "Worker " + this.name; + if (this.previous) { + return this.previous + " -> " + me; + } else { + return me; + } + } +}; + +module.exports = GenericWorker; + +},{}],29:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var ConvertWorker = require('./ConvertWorker'); +var GenericWorker = require('./GenericWorker'); +var base64 = require('../base64'); +var support = require("../support"); +var external = require("../external"); + +var NodejsStreamOutputAdapter = null; +if (support.nodestream) { + try { + NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter'); + } catch(e) {} +} + +/** + * Apply the final transformation of the data. If the user wants a Blob for + * example, it's easier to work with an U8intArray and finally do the + * ArrayBuffer/Blob conversion. + * @param {String} type the name of the final type + * @param {String|Uint8Array|Buffer} content the content to transform + * @param {String} mimeType the mime type of the content, if applicable. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. + */ +function transformZipOutput(type, content, mimeType) { + switch(type) { + case "blob" : + return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); + case "base64" : + return base64.encode(content); + default : + return utils.transformTo(type, content); + } +} + +/** + * Concatenate an array of data of the given type. + * @param {String} type the type of the data in the given array. + * @param {Array} dataArray the array containing the data chunks to concatenate + * @return {String|Uint8Array|Buffer} the concatenated data + * @throws Error if the asked type is unsupported + */ +function concat (type, dataArray) { + var i, index = 0, res = null, totalLength = 0; + for(i = 0; i < dataArray.length; i++) { + totalLength += dataArray[i].length; + } + switch(type) { + case "string": + return dataArray.join(""); + case "array": + return Array.prototype.concat.apply([], dataArray); + case "uint8array": + res = new Uint8Array(totalLength); + for(i = 0; i < dataArray.length; i++) { + res.set(dataArray[i], index); + index += dataArray[i].length; + } + return res; + case "nodebuffer": + return Buffer.concat(dataArray); + default: + throw new Error("concat : unsupported type '" + type + "'"); + } +} + +/** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {StreamHelper} helper the helper to use. + * @param {Function} updateCallback a callback called on each update. Called + * with one arg : + * - the metadata linked to the update received. + * @return Promise the promise for the accumulation. + */ +function accumulate(helper, updateCallback) { + return new external.Promise(function (resolve, reject){ + var dataArray = []; + var chunkType = helper._internalType, + resultType = helper._outputType, + mimeType = helper._mimeType; + helper + .on('data', function (data, meta) { + dataArray.push(data); + if(updateCallback) { + updateCallback(meta); + } + }) + .on('error', function(err) { + dataArray = []; + reject(err); + }) + .on('end', function (){ + try { + var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); + resolve(result); + } catch (e) { + reject(e); + } + dataArray = []; + }) + .resume(); + }); +} + +/** + * An helper to easily use workers outside of JSZip. + * @constructor + * @param {Worker} worker the worker to wrap + * @param {String} outputType the type of data expected by the use + * @param {String} mimeType the mime type of the content, if applicable. + */ +function StreamHelper(worker, outputType, mimeType) { + var internalType = outputType; + switch(outputType) { + case "blob": + case "arraybuffer": + internalType = "uint8array"; + break; + case "base64": + internalType = "string"; + break; + } + + try { + // the type used internally + this._internalType = internalType; + // the type used to output results + this._outputType = outputType; + // the mime type + this._mimeType = mimeType; + utils.checkSupport(internalType); + this._worker = worker.pipe(new ConvertWorker(internalType)); + // the last workers can be rewired without issues but we need to + // prevent any updates on previous workers. + worker.lock(); + } catch(e) { + this._worker = new GenericWorker("error"); + this._worker.error(e); + } +} + +StreamHelper.prototype = { + /** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {Function} updateCb the update callback. + * @return Promise the promise for the accumulation. + */ + accumulate : function (updateCb) { + return accumulate(this, updateCb); + }, + /** + * Add a listener on an event triggered on a stream. + * @param {String} evt the name of the event + * @param {Function} fn the listener + * @return {StreamHelper} the current helper. + */ + on : function (evt, fn) { + var self = this; + + if(evt === "data") { + this._worker.on(evt, function (chunk) { + fn.call(self, chunk.data, chunk.meta); + }); + } else { + this._worker.on(evt, function () { + utils.delay(fn, arguments, self); + }); + } + return this; + }, + /** + * Resume the flow of chunks. + * @return {StreamHelper} the current helper. + */ + resume : function () { + utils.delay(this._worker.resume, [], this._worker); + return this; + }, + /** + * Pause the flow of chunks. + * @return {StreamHelper} the current helper. + */ + pause : function () { + this._worker.pause(); + return this; + }, + /** + * Return a nodejs stream for this helper. + * @param {Function} updateCb the update callback. + * @return {NodejsStreamOutputAdapter} the nodejs stream. + */ + toNodejsStream : function (updateCb) { + utils.checkSupport("nodestream"); + if (this._outputType !== "nodebuffer") { + // an object stream containing blob/arraybuffer/uint8array/string + // is strange and I don't know if it would be useful. + // I you find this comment and have a good usecase, please open a + // bug report ! + throw new Error(this._outputType + " is not supported by this method"); + } + + return new NodejsStreamOutputAdapter(this, { + objectMode : this._outputType !== "nodebuffer" + }, updateCb); + } +}; + + +module.exports = StreamHelper; + +},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(require,module,exports){ +'use strict'; + +exports.base64 = true; +exports.array = true; +exports.string = true; +exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; +exports.nodebuffer = typeof Buffer !== "undefined"; +// contains true if JSZip can read/generate Uint8Array, false otherwise. +exports.uint8array = typeof Uint8Array !== "undefined"; + +if (typeof ArrayBuffer === "undefined") { + exports.blob = false; +} +else { + var buffer = new ArrayBuffer(0); + try { + exports.blob = new Blob([buffer], { + type: "application/zip" + }).size === 0; + } + catch (e) { + try { + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + exports.blob = builder.getBlob('application/zip').size === 0; + } + catch (e) { + exports.blob = false; + } + } +} + +try { + exports.nodestream = !!require('readable-stream').Readable; +} catch(e) { + exports.nodestream = false; +} + +},{"readable-stream":16}],31:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var support = require('./support'); +var nodejsUtils = require('./nodejsUtils'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * The following functions come from pako, from pako/lib/utils/strings + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new Array(256); +for (var i=0; i<256; i++) { + _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); +} +_utf8len[254]=_utf8len[254]=1; // Invalid sequence start + +// convert string to array (typed, when possible) +var string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + if (support.uint8array) { + buf = new Uint8Array(buf_len); + } else { + buf = new Array(buf_len); + } + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +var utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +// convert array to string +var buf2string = function (buf) { + var str, i, out, c, c_len; + var len = buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + // shrinkBuf(utf16buf, out) + if (utf16buf.length !== out) { + if(utf16buf.subarray) { + utf16buf = utf16buf.subarray(0, out); + } else { + utf16buf.length = out; + } + } + + // return String.fromCharCode.apply(null, utf16buf); + return utils.applyFromCharCode(utf16buf); +}; + + +// That's all for the pako functions. + + +/** + * Transform a javascript string into an array (typed if possible) of bytes, + * UTF-8 encoded. + * @param {String} str the string to encode + * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. + */ +exports.utf8encode = function utf8encode(str) { + if (support.nodebuffer) { + return nodejsUtils.newBufferFrom(str, "utf-8"); + } + + return string2buf(str); +}; + + +/** + * Transform a bytes array (or a representation) representing an UTF-8 encoded + * string into a javascript string. + * @param {Array|Uint8Array|Buffer} buf the data de decode + * @return {String} the decoded string. + */ +exports.utf8decode = function utf8decode(buf) { + if (support.nodebuffer) { + return utils.transformTo("nodebuffer", buf).toString("utf-8"); + } + + buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); + + return buf2string(buf); +}; + +/** + * A worker to decode utf8 encoded binary chunks into string chunks. + * @constructor + */ +function Utf8DecodeWorker() { + GenericWorker.call(this, "utf-8 decode"); + // the last bytes if a chunk didn't end with a complete codepoint. + this.leftOver = null; +} +utils.inherits(Utf8DecodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8DecodeWorker.prototype.processChunk = function (chunk) { + + var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data); + + // 1st step, re-use what's left of the previous chunk + if (this.leftOver && this.leftOver.length) { + if(support.uint8array) { + var previousData = data; + data = new Uint8Array(previousData.length + this.leftOver.length); + data.set(this.leftOver, 0); + data.set(previousData, this.leftOver.length); + } else { + data = this.leftOver.concat(data); + } + this.leftOver = null; + } + + var nextBoundary = utf8border(data); + var usableData = data; + if (nextBoundary !== data.length) { + if (support.uint8array) { + usableData = data.subarray(0, nextBoundary); + this.leftOver = data.subarray(nextBoundary, data.length); + } else { + usableData = data.slice(0, nextBoundary); + this.leftOver = data.slice(nextBoundary, data.length); + } + } + + this.push({ + data : exports.utf8decode(usableData), + meta : chunk.meta + }); +}; + +/** + * @see GenericWorker.flush + */ +Utf8DecodeWorker.prototype.flush = function () { + if(this.leftOver && this.leftOver.length) { + this.push({ + data : exports.utf8decode(this.leftOver), + meta : {} + }); + this.leftOver = null; + } +}; +exports.Utf8DecodeWorker = Utf8DecodeWorker; + +/** + * A worker to endcode string chunks into utf8 encoded binary chunks. + * @constructor + */ +function Utf8EncodeWorker() { + GenericWorker.call(this, "utf-8 encode"); +} +utils.inherits(Utf8EncodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8EncodeWorker.prototype.processChunk = function (chunk) { + this.push({ + data : exports.utf8encode(chunk.data), + meta : chunk.meta + }); +}; +exports.Utf8EncodeWorker = Utf8EncodeWorker; + +},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){ +'use strict'; + +var support = require('./support'); +var base64 = require('./base64'); +var nodejsUtils = require('./nodejsUtils'); +var setImmediate = require('core-js/library/fn/set-immediate'); +var external = require("./external"); + + +/** + * Convert a string that pass as a "binary string": it should represent a byte + * array but may have > 255 char codes. Be sure to take only the first byte + * and returns the byte array. + * @param {String} str the string to transform. + * @return {Array|Uint8Array} the string in a binary format. + */ +function string2binary(str) { + var result = null; + if (support.uint8array) { + result = new Uint8Array(str.length); + } else { + result = new Array(str.length); + } + return stringToArrayLike(str, result); +} + +/** + * Create a new blob with the given content and the given type. + * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use + * an Uint8Array because the stock browser of android 4 won't accept it (it + * will be silently converted to a string, "[object Uint8Array]"). + * + * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: + * when a large amount of Array is used to create the Blob, the amount of + * memory consumed is nearly 100 times the original data amount. + * + * @param {String} type the mime type of the blob. + * @return {Blob} the created blob. + */ +exports.newBlob = function(part, type) { + exports.checkSupport("blob"); + + try { + // Blob constructor + return new Blob([part], { + type: type + }); + } + catch (e) { + + try { + // deprecated, browser only, old way + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(part); + return builder.getBlob(type); + } + catch (e) { + + // well, fuck ?! + throw new Error("Bug : can't construct the Blob."); + } + } + + +}; +/** + * The identity function. + * @param {Object} input the input. + * @return {Object} the same input. + */ +function identity(input) { + return input; +} + +/** + * Fill in an array with a string. + * @param {String} str the string to use. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. + */ +function stringToArrayLike(str, array) { + for (var i = 0; i < str.length; ++i) { + array[i] = str.charCodeAt(i) & 0xFF; + } + return array; +} + +/** + * An helper for the function arrayLikeToString. + * This contains static informations and functions that + * can be optimized by the browser JIT compiler. + */ +var arrayToStringHelper = { + /** + * Transform an array of int into a string, chunk by chunk. + * See the performances notes on arrayLikeToString. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @param {String} type the type of the array. + * @param {Integer} chunk the chunk size. + * @return {String} the resulting string. + * @throws Error if the chunk is too big for the stack. + */ + stringifyByChunk: function(array, type, chunk) { + var result = [], k = 0, len = array.length; + // shortcut + if (len <= chunk) { + return String.fromCharCode.apply(null, array); + } + while (k < len) { + if (type === "array" || type === "nodebuffer") { + result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); + } + else { + result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); + } + k += chunk; + } + return result.join(""); + }, + /** + * Call String.fromCharCode on every item in the array. + * This is the naive implementation, which generate A LOT of intermediate string. + * This should be used when everything else fail. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ + stringifyByChar: function(array){ + var resultStr = ""; + for(var i = 0; i < array.length; i++) { + resultStr += String.fromCharCode(array[i]); + } + return resultStr; + }, + applyCanBeUsed : { + /** + * true if the browser accepts to use String.fromCharCode on Uint8Array + */ + uint8array : (function () { + try { + return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; + } catch (e) { + return false; + } + })(), + /** + * true if the browser accepts to use String.fromCharCode on nodejs Buffer. + */ + nodebuffer : (function () { + try { + return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; + } catch (e) { + return false; + } + })() + } +}; + +/** + * Transform an array-like object to a string. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ +function arrayLikeToString(array) { + // Performances notes : + // -------------------- + // String.fromCharCode.apply(null, array) is the fastest, see + // see http://jsperf.com/converting-a-uint8array-to-a-string/2 + // but the stack is limited (and we can get huge arrays !). + // + // result += String.fromCharCode(array[i]); generate too many strings ! + // + // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 + // TODO : we now have workers that split the work. Do we still need that ? + var chunk = 65536, + type = exports.getTypeOf(array), + canUseApply = true; + if (type === "uint8array") { + canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; + } else if (type === "nodebuffer") { + canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; + } + + if (canUseApply) { + while (chunk > 1) { + try { + return arrayToStringHelper.stringifyByChunk(array, type, chunk); + } catch (e) { + chunk = Math.floor(chunk / 2); + } + } + } + + // no apply or chunk error : slow and painful algorithm + // default browser on android 4.* + return arrayToStringHelper.stringifyByChar(array); +} + +exports.applyFromCharCode = arrayLikeToString; + + +/** + * Copy the data from an array-like to an other array-like. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. + */ +function arrayLikeToArrayLike(arrayFrom, arrayTo) { + for (var i = 0; i < arrayFrom.length; i++) { + arrayTo[i] = arrayFrom[i]; + } + return arrayTo; +} + +// a matrix containing functions to transform everything into everything. +var transform = {}; + +// string to ? +transform["string"] = { + "string": identity, + "array": function(input) { + return stringToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["string"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return stringToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": function(input) { + return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); + } +}; + +// array to ? +transform["array"] = { + "string": arrayLikeToString, + "array": identity, + "arraybuffer": function(input) { + return (new Uint8Array(input)).buffer; + }, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// arraybuffer to ? +transform["arraybuffer"] = { + "string": function(input) { + return arrayLikeToString(new Uint8Array(input)); + }, + "array": function(input) { + return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); + }, + "arraybuffer": identity, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(new Uint8Array(input)); + } +}; + +// uint8array to ? +transform["uint8array"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return input.buffer; + }, + "uint8array": identity, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// nodebuffer to ? +transform["nodebuffer"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["nodebuffer"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return arrayLikeToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": identity +}; + +/** + * Transform an input into any type. + * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. + * If no output type is specified, the unmodified input will be returned. + * @param {String} outputType the output type. + * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. + * @throws {Error} an Error if the browser doesn't support the requested output type. + */ +exports.transformTo = function(outputType, input) { + if (!input) { + // undefined, null, etc + // an empty string won't harm. + input = ""; + } + if (!outputType) { + return input; + } + exports.checkSupport(outputType); + var inputType = exports.getTypeOf(input); + var result = transform[inputType][outputType](input); + return result; +}; + +/** + * Return the type of the input. + * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. + * @param {Object} input the input to identify. + * @return {String} the (lowercase) type of the input. + */ +exports.getTypeOf = function(input) { + if (typeof input === "string") { + return "string"; + } + if (Object.prototype.toString.call(input) === "[object Array]") { + return "array"; + } + if (support.nodebuffer && nodejsUtils.isBuffer(input)) { + return "nodebuffer"; + } + if (support.uint8array && input instanceof Uint8Array) { + return "uint8array"; + } + if (support.arraybuffer && input instanceof ArrayBuffer) { + return "arraybuffer"; + } +}; + +/** + * Throw an exception if the type is not supported. + * @param {String} type the type to check. + * @throws {Error} an Error if the browser doesn't support the requested type. + */ +exports.checkSupport = function(type) { + var supported = support[type.toLowerCase()]; + if (!supported) { + throw new Error(type + " is not supported by this platform"); + } +}; + +exports.MAX_VALUE_16BITS = 65535; +exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 + +/** + * Prettify a string read as binary. + * @param {string} str the string to prettify. + * @return {string} a pretty string. + */ +exports.pretty = function(str) { + var res = '', + code, i; + for (i = 0; i < (str || "").length; i++) { + code = str.charCodeAt(i); + res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); + } + return res; +}; + +/** + * Defer the call of a function. + * @param {Function} callback the function to call asynchronously. + * @param {Array} args the arguments to give to the callback. + */ +exports.delay = function(callback, args, self) { + setImmediate(function () { + callback.apply(self || null, args || []); + }); +}; + +/** + * Extends a prototype with an other, without calling a constructor with + * side effects. Inspired by nodejs' `utils.inherits` + * @param {Function} ctor the constructor to augment + * @param {Function} superCtor the parent constructor to use + */ +exports.inherits = function (ctor, superCtor) { + var Obj = function() {}; + Obj.prototype = superCtor.prototype; + ctor.prototype = new Obj(); +}; + +/** + * Merge the objects passed as parameters into a new one. + * @private + * @param {...Object} var_args All objects to merge. + * @return {Object} a new object with the data of the others. + */ +exports.extend = function() { + var result = {}, i, attr; + for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers + for (attr in arguments[i]) { + if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { + result[attr] = arguments[i][attr]; + } + } + } + return result; +}; + +/** + * Transform arbitrary content into a Promise. + * @param {String} name a name for the content being processed. + * @param {Object} inputData the content to process. + * @param {Boolean} isBinary true if the content is not an unicode string + * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. + * @param {Boolean} isBase64 true if the string content is encoded with base64. + * @return {Promise} a promise in a format usable by JSZip. + */ +exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { + + // if inputData is already a promise, this flatten it. + var promise = external.Promise.resolve(inputData).then(function(data) { + + + var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); + + if (isBlob && typeof FileReader !== "undefined") { + return new external.Promise(function (resolve, reject) { + var reader = new FileReader(); + + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e.target.error); + }; + reader.readAsArrayBuffer(data); + }); + } else { + return data; + } + }); + + return promise.then(function(data) { + var dataType = exports.getTypeOf(data); + + if (!dataType) { + return external.Promise.reject( + new Error("Can't read the data of '" + name + "'. Is it " + + "in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") + ); + } + // special case : it's way easier to work with Uint8Array than with ArrayBuffer + if (dataType === "arraybuffer") { + data = exports.transformTo("uint8array", data); + } else if (dataType === "string") { + if (isBase64) { + data = base64.decode(data); + } + else if (isBinary) { + // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask + if (isOptimizedBinaryString !== true) { + // this is a string, not in a base64 format. + // Be sure that this is a correct "binary string" + data = string2binary(data); + } + } + } + return data; + }); +}; + +},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"core-js/library/fn/set-immediate":36}],33:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var sig = require('./signature'); +var ZipEntry = require('./zipEntry'); +var utf8 = require('./utf8'); +var support = require('./support'); +// class ZipEntries {{{ +/** + * All the entries in the zip file. + * @constructor + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntries(loadOptions) { + this.files = []; + this.loadOptions = loadOptions; +} +ZipEntries.prototype = { + /** + * Check that the reader is on the specified signature. + * @param {string} expectedSignature the expected signature. + * @throws {Error} if it is an other signature. + */ + checkSignature: function(expectedSignature) { + if (!this.reader.readAndCheckSignature(expectedSignature)) { + this.reader.index -= 4; + var signature = this.reader.readString(4); + throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); + } + }, + /** + * Check if the given signature is at the given index. + * @param {number} askedIndex the index to check. + * @param {string} expectedSignature the signature to expect. + * @return {boolean} true if the signature is here, false otherwise. + */ + isSignature: function(askedIndex, expectedSignature) { + var currentIndex = this.reader.index; + this.reader.setIndex(askedIndex); + var signature = this.reader.readString(4); + var result = signature === expectedSignature; + this.reader.setIndex(currentIndex); + return result; + }, + /** + * Read the end of the central directory. + */ + readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2); + this.diskWithCentralDirStart = this.reader.readInt(2); + this.centralDirRecordsOnThisDisk = this.reader.readInt(2); + this.centralDirRecords = this.reader.readInt(2); + this.centralDirSize = this.reader.readInt(4); + this.centralDirOffset = this.reader.readInt(4); + + this.zipCommentLength = this.reader.readInt(2); + // warning : the encoding depends of the system locale + // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. + // On a windows machine, this field is encoded with the localized windows code page. + var zipComment = this.reader.readData(this.zipCommentLength); + var decodeParamType = support.uint8array ? "uint8array" : "array"; + // To get consistent behavior with the generation part, we will assume that + // this is utf8 encoded unless specified otherwise. + var decodeContent = utils.transformTo(decodeParamType, zipComment); + this.zipComment = this.loadOptions.decodeFileName(decodeContent); + }, + /** + * Read the end of the Zip 64 central directory. + * Not merged with the method readEndOfCentral : + * The end of central can coexist with its Zip64 brother, + * I don't want to read the wrong number of bytes ! + */ + readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8); + this.reader.skip(4); + // this.versionMadeBy = this.reader.readString(2); + // this.versionNeeded = this.reader.readInt(2); + this.diskNumber = this.reader.readInt(4); + this.diskWithCentralDirStart = this.reader.readInt(4); + this.centralDirRecordsOnThisDisk = this.reader.readInt(8); + this.centralDirRecords = this.reader.readInt(8); + this.centralDirSize = this.reader.readInt(8); + this.centralDirOffset = this.reader.readInt(8); + + this.zip64ExtensibleData = {}; + var extraDataSize = this.zip64EndOfCentralSize - 44, + index = 0, + extraFieldId, + extraFieldLength, + extraFieldValue; + while (index < extraDataSize) { + extraFieldId = this.reader.readInt(2); + extraFieldLength = this.reader.readInt(4); + extraFieldValue = this.reader.readData(extraFieldLength); + this.zip64ExtensibleData[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Read the end of the Zip 64 central directory locator. + */ + readBlockZip64EndOfCentralLocator: function() { + this.diskWithZip64CentralDirStart = this.reader.readInt(4); + this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); + this.disksCount = this.reader.readInt(4); + if (this.disksCount > 1) { + throw new Error("Multi-volumes zip are not supported"); + } + }, + /** + * Read the local files, based on the offset read in the central part. + */ + readLocalFiles: function() { + var i, file; + for (i = 0; i < this.files.length; i++) { + file = this.files[i]; + this.reader.setIndex(file.localHeaderOffset); + this.checkSignature(sig.LOCAL_FILE_HEADER); + file.readLocalPart(this.reader); + file.handleUTF8(); + file.processAttributes(); + } + }, + /** + * Read the central directory. + */ + readCentralDir: function() { + var file; + + this.reader.setIndex(this.centralDirOffset); + while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) { + file = new ZipEntry({ + zip64: this.zip64 + }, this.loadOptions); + file.readCentralPart(this.reader); + this.files.push(file); + } + + if (this.centralDirRecords !== this.files.length) { + if (this.centralDirRecords !== 0 && this.files.length === 0) { + // We expected some records but couldn't find ANY. + // This is really suspicious, as if something went wrong. + throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); + } else { + // We found some records but not all. + // Something is wrong but we got something for the user: no error here. + // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length); + } + } + }, + /** + * Read the end of central directory. + */ + readEndOfCentral: function() { + var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); + if (offset < 0) { + // Check if the content is a truncated zip or complete garbage. + // A "LOCAL_FILE_HEADER" is not required at the beginning (auto + // extractible zip for example) but it can give a good hint. + // If an ajax request was used without responseType, we will also + // get unreadable data. + var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER); + + if (isGarbage) { + throw new Error("Can't find end of central directory : is this a zip file ? " + + "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"); + } else { + throw new Error("Corrupted zip: can't find end of central directory"); + } + + } + this.reader.setIndex(offset); + var endOfCentralDirOffset = offset; + this.checkSignature(sig.CENTRAL_DIRECTORY_END); + this.readBlockEndOfCentral(); + + + /* extract from the zip spec : + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + */ + if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { + this.zip64 = true; + + /* + Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from + the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents + all numbers as 64-bit double precision IEEE 754 floating point numbers. + So, we have 53bits for integers and bitwise operations treat everything as 32bits. + see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators + and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 + */ + + // should look for a zip64 EOCD locator + offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + if (offset < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + this.readBlockZip64EndOfCentralLocator(); + + // now the zip64 EOCD record + if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) { + // console.warn("ZIP64 end of central directory not where expected."); + this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + if (this.relativeOffsetEndOfZip64CentralDir < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); + } + } + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + this.readBlockZip64EndOfCentral(); + } + + var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize; + if (this.zip64) { + expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator + expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize; + } + + var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset; + + if (extraBytes > 0) { + // console.warn(extraBytes, "extra bytes at beginning or within zipfile"); + if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) { + // The offsets seem wrong, but we have something at the specified offset. + // So… we keep it. + } else { + // the offset is wrong, update the "zero" of the reader + // this happens if data has been prepended (crx files for example) + this.reader.zero = extraBytes; + } + } else if (extraBytes < 0) { + throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes."); + } + }, + prepareReader: function(data) { + this.reader = readerFor(data); + }, + /** + * Read a zip file and create ZipEntries. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. + */ + load: function(data) { + this.prepareReader(data); + this.readEndOfCentral(); + this.readCentralDir(); + this.readLocalFiles(); + } +}; +// }}} end of ZipEntries +module.exports = ZipEntries; + +},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var CompressedObject = require('./compressedObject'); +var crc32fn = require('./crc32'); +var utf8 = require('./utf8'); +var compressions = require('./compressions'); +var support = require('./support'); + +var MADE_BY_DOS = 0x00; +var MADE_BY_UNIX = 0x03; + +/** + * Find a compression registered in JSZip. + * @param {string} compressionMethod the method magic to find. + * @return {Object|null} the JSZip compression object, null if none found. + */ +var findCompression = function(compressionMethod) { + for (var method in compressions) { + if (!compressions.hasOwnProperty(method)) { + continue; + } + if (compressions[method].magic === compressionMethod) { + return compressions[method]; + } + } + return null; +}; + +// class ZipEntry {{{ +/** + * An entry in the zip file. + * @constructor + * @param {Object} options Options of the current file. + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntry(options, loadOptions) { + this.options = options; + this.loadOptions = loadOptions; +} +ZipEntry.prototype = { + /** + * say if the file is encrypted. + * @return {boolean} true if the file is encrypted, false otherwise. + */ + isEncrypted: function() { + // bit 1 is set + return (this.bitFlag & 0x0001) === 0x0001; + }, + /** + * say if the file has utf-8 filename/comment. + * @return {boolean} true if the filename/comment is in utf-8, false otherwise. + */ + useUTF8: function() { + // bit 11 is set + return (this.bitFlag & 0x0800) === 0x0800; + }, + /** + * Read the local part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readLocalPart: function(reader) { + var compression, localExtraFieldsLength; + + // we already know everything from the central dir ! + // If the central dir data are false, we are doomed. + // On the bright side, the local part is scary : zip64, data descriptors, both, etc. + // The less data we get here, the more reliable this should be. + // Let's skip the whole header and dash to the data ! + reader.skip(22); + // in some zip created on windows, the filename stored in the central dir contains \ instead of /. + // Strangely, the filename here is OK. + // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes + // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... + // Search "unzip mismatching "local" filename continuing with "central" filename version" on + // the internet. + // + // I think I see the logic here : the central directory is used to display + // content and the local directory is used to extract the files. Mixing / and \ + // may be used to display \ to windows users and use / when extracting the files. + // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 + this.fileNameLength = reader.readInt(2); + localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir + // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding. + this.fileName = reader.readData(this.fileNameLength); + reader.skip(localExtraFieldsLength); + + if (this.compressedSize === -1 || this.uncompressedSize === -1) { + throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)"); + } + + compression = findCompression(this.compressionMethod); + if (compression === null) { // no compression found + throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")"); + } + this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize)); + }, + + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readCentralPart: function(reader) { + this.versionMadeBy = reader.readInt(2); + reader.skip(2); + // this.versionNeeded = reader.readInt(2); + this.bitFlag = reader.readInt(2); + this.compressionMethod = reader.readString(2); + this.date = reader.readDate(); + this.crc32 = reader.readInt(4); + this.compressedSize = reader.readInt(4); + this.uncompressedSize = reader.readInt(4); + var fileNameLength = reader.readInt(2); + this.extraFieldsLength = reader.readInt(2); + this.fileCommentLength = reader.readInt(2); + this.diskNumberStart = reader.readInt(2); + this.internalFileAttributes = reader.readInt(2); + this.externalFileAttributes = reader.readInt(4); + this.localHeaderOffset = reader.readInt(4); + + if (this.isEncrypted()) { + throw new Error("Encrypted zip are not supported"); + } + + // will be read in the local part, see the comments there + reader.skip(fileNameLength); + this.readExtraFields(reader); + this.parseZIP64ExtraField(reader); + this.fileComment = reader.readData(this.fileCommentLength); + }, + + /** + * Parse the external file attributes and get the unix/dos permissions. + */ + processAttributes: function () { + this.unixPermissions = null; + this.dosPermissions = null; + var madeBy = this.versionMadeBy >> 8; + + // Check if we have the DOS directory flag set. + // We look for it in the DOS and UNIX permissions + // but some unknown platform could set it as a compatibility flag. + this.dir = this.externalFileAttributes & 0x0010 ? true : false; + + if(madeBy === MADE_BY_DOS) { + // first 6 bits (0 to 5) + this.dosPermissions = this.externalFileAttributes & 0x3F; + } + + if(madeBy === MADE_BY_UNIX) { + this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; + // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); + } + + // fail safe : if the name ends with a / it probably means a folder + if (!this.dir && this.fileNameStr.slice(-1) === '/') { + this.dir = true; + } + }, + + /** + * Parse the ZIP64 extra field and merge the info in the current ZipEntry. + * @param {DataReader} reader the reader to use. + */ + parseZIP64ExtraField: function(reader) { + + if (!this.extraFields[0x0001]) { + return; + } + + // should be something, preparing the extra reader + var extraReader = readerFor(this.extraFields[0x0001].value); + + // I really hope that these 64bits integer can fit in 32 bits integer, because js + // won't let us have more. + if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { + this.uncompressedSize = extraReader.readInt(8); + } + if (this.compressedSize === utils.MAX_VALUE_32BITS) { + this.compressedSize = extraReader.readInt(8); + } + if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { + this.localHeaderOffset = extraReader.readInt(8); + } + if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { + this.diskNumberStart = extraReader.readInt(4); + } + }, + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readExtraFields: function(reader) { + var end = reader.index + this.extraFieldsLength, + extraFieldId, + extraFieldLength, + extraFieldValue; + + if (!this.extraFields) { + this.extraFields = {}; + } + + while (reader.index < end) { + extraFieldId = reader.readInt(2); + extraFieldLength = reader.readInt(2); + extraFieldValue = reader.readData(extraFieldLength); + + this.extraFields[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Apply an UTF8 transformation if needed. + */ + handleUTF8: function() { + var decodeParamType = support.uint8array ? "uint8array" : "array"; + if (this.useUTF8()) { + this.fileNameStr = utf8.utf8decode(this.fileName); + this.fileCommentStr = utf8.utf8decode(this.fileComment); + } else { + var upath = this.findExtraFieldUnicodePath(); + if (upath !== null) { + this.fileNameStr = upath; + } else { + // ASCII text or unsupported code page + var fileNameByteArray = utils.transformTo(decodeParamType, this.fileName); + this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray); + } + + var ucomment = this.findExtraFieldUnicodeComment(); + if (ucomment !== null) { + this.fileCommentStr = ucomment; + } else { + // ASCII text or unsupported code page + var commentByteArray = utils.transformTo(decodeParamType, this.fileComment); + this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray); + } + } + }, + + /** + * Find the unicode path declared in the extra field, if any. + * @return {String} the unicode path, null otherwise. + */ + findExtraFieldUnicodePath: function() { + var upathField = this.extraFields[0x7075]; + if (upathField) { + var extraReader = readerFor(upathField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the filename changed, this field is out of date. + if (crc32fn(this.fileName) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(upathField.length - 5)); + } + return null; + }, + + /** + * Find the unicode comment declared in the extra field, if any. + * @return {String} the unicode comment, null otherwise. + */ + findExtraFieldUnicodeComment: function() { + var ucommentField = this.extraFields[0x6375]; + if (ucommentField) { + var extraReader = readerFor(ucommentField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the comment changed, this field is out of date. + if (crc32fn(this.fileComment) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(ucommentField.length - 5)); + } + return null; + } +}; +module.exports = ZipEntry; + +},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(require,module,exports){ +'use strict'; + +var StreamHelper = require('./stream/StreamHelper'); +var DataWorker = require('./stream/DataWorker'); +var utf8 = require('./utf8'); +var CompressedObject = require('./compressedObject'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * A simple object representing a file in the zip file. + * @constructor + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data + * @param {Object} options the options of the file + */ +var ZipObject = function(name, data, options) { + this.name = name; + this.dir = options.dir; + this.date = options.date; + this.comment = options.comment; + this.unixPermissions = options.unixPermissions; + this.dosPermissions = options.dosPermissions; + + this._data = data; + this._dataBinary = options.binary; + // keep only the compression + this.options = { + compression : options.compression, + compressionOptions : options.compressionOptions + }; +}; + +ZipObject.prototype = { + /** + * Create an internal stream for the content of this object. + * @param {String} type the type of each chunk. + * @return StreamHelper the stream. + */ + internalStream: function (type) { + var result = null, outputType = "string"; + try { + if (!type) { + throw new Error("No output type specified."); + } + outputType = type.toLowerCase(); + var askUnicodeString = outputType === "string" || outputType === "text"; + if (outputType === "binarystring" || outputType === "text") { + outputType = "string"; + } + result = this._decompressWorker(); + + var isUnicodeString = !this._dataBinary; + + if (isUnicodeString && !askUnicodeString) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + if (!isUnicodeString && askUnicodeString) { + result = result.pipe(new utf8.Utf8DecodeWorker()); + } + } catch (e) { + result = new GenericWorker("error"); + result.error(e); + } + + return new StreamHelper(result, outputType, ""); + }, + + /** + * Prepare the content in the asked type. + * @param {String} type the type of the result. + * @param {Function} onUpdate a function to call on each internal update. + * @return Promise the promise of the result. + */ + async: function (type, onUpdate) { + return this.internalStream(type).accumulate(onUpdate); + }, + + /** + * Prepare the content as a nodejs stream. + * @param {String} type the type of each chunk. + * @param {Function} onUpdate a function to call on each internal update. + * @return Stream the stream. + */ + nodeStream: function (type, onUpdate) { + return this.internalStream(type || "nodebuffer").toNodejsStream(onUpdate); + }, + + /** + * Return a worker for the compressed content. + * @private + * @param {Object} compression the compression object to use. + * @param {Object} compressionOptions the options to use when compressing. + * @return Worker the worker. + */ + _compressWorker: function (compression, compressionOptions) { + if ( + this._data instanceof CompressedObject && + this._data.compression.magic === compression.magic + ) { + return this._data.getCompressedWorker(); + } else { + var result = this._decompressWorker(); + if(!this._dataBinary) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + return CompressedObject.createWorkerFrom(result, compression, compressionOptions); + } + }, + /** + * Return a worker for the decompressed content. + * @private + * @return Worker the worker. + */ + _decompressWorker : function () { + if (this._data instanceof CompressedObject) { + return this._data.getContentWorker(); + } else if (this._data instanceof GenericWorker) { + return this._data; + } else { + return new DataWorker(this._data); + } + } +}; + +var removedMethods = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"]; +var removedFn = function () { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); +}; + +for(var i = 0; i < removedMethods.length; i++) { + ZipObject.prototype[removedMethods[i]] = removedFn; +} +module.exports = ZipObject; + +},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(require,module,exports){ +require('../modules/web.immediate'); +module.exports = require('../modules/_core').setImmediate; +},{"../modules/_core":40,"../modules/web.immediate":56}],37:[function(require,module,exports){ +module.exports = function(it){ + if(typeof it != 'function')throw TypeError(it + ' is not a function!'); + return it; +}; +},{}],38:[function(require,module,exports){ +var isObject = require('./_is-object'); +module.exports = function(it){ + if(!isObject(it))throw TypeError(it + ' is not an object!'); + return it; +}; +},{"./_is-object":51}],39:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = function(it){ + return toString.call(it).slice(8, -1); +}; +},{}],40:[function(require,module,exports){ +var core = module.exports = {version: '2.3.0'}; +if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef +},{}],41:[function(require,module,exports){ +// optional / simple context binding +var aFunction = require('./_a-function'); +module.exports = function(fn, that, length){ + aFunction(fn); + if(that === undefined)return fn; + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; +}; +},{"./_a-function":37}],42:[function(require,module,exports){ +// Thank's IE8 for his funny defineProperty +module.exports = !require('./_fails')(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_fails":45}],43:[function(require,module,exports){ +var isObject = require('./_is-object') + , document = require('./_global').document + // in old IE typeof document.createElement is 'object' + , is = isObject(document) && isObject(document.createElement); +module.exports = function(it){ + return is ? document.createElement(it) : {}; +}; +},{"./_global":46,"./_is-object":51}],44:[function(require,module,exports){ +var global = require('./_global') + , core = require('./_core') + , ctx = require('./_ctx') + , hide = require('./_hide') + , PROTOTYPE = 'prototype'; + +var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , IS_WRAP = type & $export.W + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] + , key, own, out; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if(own && key in exports)continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function(C){ + var F = function(a, b, c){ + if(this instanceof C){ + switch(arguments.length){ + case 0: return new C; + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if(IS_PROTO){ + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); + } + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; +},{"./_core":40,"./_ctx":41,"./_global":46,"./_hide":47}],45:[function(require,module,exports){ +module.exports = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } +}; +},{}],46:[function(require,module,exports){ +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); +if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef +},{}],47:[function(require,module,exports){ +var dP = require('./_object-dp') + , createDesc = require('./_property-desc'); +module.exports = require('./_descriptors') ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); +} : function(object, key, value){ + object[key] = value; + return object; +}; +},{"./_descriptors":42,"./_object-dp":52,"./_property-desc":53}],48:[function(require,module,exports){ +module.exports = require('./_global').document && document.documentElement; +},{"./_global":46}],49:[function(require,module,exports){ +module.exports = !require('./_descriptors') && !require('./_fails')(function(){ + return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_descriptors":42,"./_dom-create":43,"./_fails":45}],50:[function(require,module,exports){ +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function(fn, args, that){ + var un = that === undefined; + switch(args.length){ + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; +},{}],51:[function(require,module,exports){ +module.exports = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; +},{}],52:[function(require,module,exports){ +var anObject = require('./_an-object') + , IE8_DOM_DEFINE = require('./_ie8-dom-define') + , toPrimitive = require('./_to-primitive') + , dP = Object.defineProperty; + +exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){ + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if(IE8_DOM_DEFINE)try { + return dP(O, P, Attributes); + } catch(e){ /* empty */ } + if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); + if('value' in Attributes)O[P] = Attributes.value; + return O; +}; +},{"./_an-object":38,"./_descriptors":42,"./_ie8-dom-define":49,"./_to-primitive":55}],53:[function(require,module,exports){ +module.exports = function(bitmap, value){ + return { + enumerable : !(bitmap & 1), + configurable: !(bitmap & 2), + writable : !(bitmap & 4), + value : value + }; +}; +},{}],54:[function(require,module,exports){ +var ctx = require('./_ctx') + , invoke = require('./_invoke') + , html = require('./_html') + , cel = require('./_dom-create') + , global = require('./_global') + , process = global.process + , setTask = global.setImmediate + , clearTask = global.clearImmediate + , MessageChannel = global.MessageChannel + , counter = 0 + , queue = {} + , ONREADYSTATECHANGE = 'onreadystatechange' + , defer, channel, port; +var run = function(){ + var id = +this; + if(queue.hasOwnProperty(id)){ + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function(event){ + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if(!setTask || !clearTask){ + setTask = function setImmediate(fn){ + var args = [], i = 1; + while(arguments.length > i)args.push(arguments[i++]); + queue[++counter] = function(){ + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id){ + delete queue[id]; + }; + // Node.js 0.8- + if(require('./_cof')(process) == 'process'){ + defer = function(id){ + process.nextTick(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if(MessageChannel){ + channel = new MessageChannel; + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ + defer = function(id){ + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if(ONREADYSTATECHANGE in cel('script')){ + defer = function(id){ + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function(id){ + setTimeout(ctx(run, id, 1), 0); + }; + } +} +module.exports = { + set: setTask, + clear: clearTask +}; +},{"./_cof":39,"./_ctx":41,"./_dom-create":43,"./_global":46,"./_html":48,"./_invoke":50}],55:[function(require,module,exports){ +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = require('./_is-object'); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function(it, S){ + if(!isObject(it))return it; + var fn, val; + if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; + if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + throw TypeError("Can't convert object to primitive value"); +}; +},{"./_is-object":51}],56:[function(require,module,exports){ +var $export = require('./_export') + , $task = require('./_task'); +$export($export.G + $export.B, { + setImmediate: $task.set, + clearImmediate: $task.clear +}); +},{"./_export":44,"./_task":54}],57:[function(require,module,exports){ +(function (global){ +'use strict'; +var Mutation = global.MutationObserver || global.WebKitMutationObserver; + +var scheduleDrain; + +{ + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + scheduleDrain = function () { + element.data = (called = ++called % 2); + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + + // Create a + + - - +
    - -
    - - - - - - - -
    - - -
    -

    ACF (Bungee) 0.5.0-SNAPSHOT API

    -
    -
    - - - - - - - - - - - - - - - - - - - - -
    Packages 
    PackageDescription
    co.aikar.commands 
    co.aikar.commands.bungee.contexts 
    co.aikar.commands.contexts 
    -
    - -
    - - - - - - - -
    - - -

    Copyright © 2019. All rights reserved.

    +

    index.html

    +
    diff --git a/docs/acf-bungee/overview-tree.html b/docs/acf-bungee/overview-tree.html index ed31aac9..29d63399 100644 --- a/docs/acf-bungee/overview-tree.html +++ b/docs/acf-bungee/overview-tree.html @@ -1,12 +1,21 @@ - + - Class Hierarchy (ACF (Bungee) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Hierarchy For All Packages

    Package Hierarchies: @@ -78,94 +102,101 @@
    +

    Class Hierarchy

    +
    +

    Enum Hierarchy

    +
    +
    + diff --git a/docs/acf-bungee/package-search-index.js b/docs/acf-bungee/package-search-index.js new file mode 100644 index 00000000..3c1c205a --- /dev/null +++ b/docs/acf-bungee/package-search-index.js @@ -0,0 +1 @@ +packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"co.aikar.commands"},{"l":"co.aikar.commands.bungee.contexts"},{"l":"co.aikar.commands.contexts"}] \ No newline at end of file diff --git a/docs/acf-bungee/package-search-index.zip b/docs/acf-bungee/package-search-index.zip new file mode 100644 index 00000000..9c9d5e26 Binary files /dev/null and b/docs/acf-bungee/package-search-index.zip differ diff --git a/docs/acf-bungee/resources/glass.png b/docs/acf-bungee/resources/glass.png new file mode 100644 index 00000000..a7f591f4 Binary files /dev/null and b/docs/acf-bungee/resources/glass.png differ diff --git a/docs/acf-bungee/resources/x.png b/docs/acf-bungee/resources/x.png new file mode 100644 index 00000000..30548a75 Binary files /dev/null and b/docs/acf-bungee/resources/x.png differ diff --git a/docs/acf-bungee/script.js b/docs/acf-bungee/script.js index b3463569..0eaaf535 100644 --- a/docs/acf-bungee/script.js +++ b/docs/acf-bungee/script.js @@ -1,9 +1,114 @@ -function show(type) -{ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var moduleSearchIndex; +var packageSearchIndex; +var typeSearchIndex; +var memberSearchIndex; +var tagSearchIndex; +function loadScripts(doc, tag) { + createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); + if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || + window.navigator.userAgent.indexOf('Edge/') > 0) { + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); + } + createElem(doc, tag, 'search.js'); + + $.get(pathtoroot + "module-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + moduleSearchIndex = JSON.parse(zip.file("module-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "package-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + packageSearchIndex = JSON.parse(zip.file("package-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "type-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + typeSearchIndex = JSON.parse(zip.file("type-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "member-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + memberSearchIndex = JSON.parse(zip.file("member-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "tag-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + tagSearchIndex = JSON.parse(zip.file("tag-search-index.json").asText()); + }); + }); + if (!moduleSearchIndex) { + createElem(doc, tag, 'module-search-index.js'); + } + if (!packageSearchIndex) { + createElem(doc, tag, 'package-search-index.js'); + } + if (!typeSearchIndex) { + createElem(doc, tag, 'type-search-index.js'); + } + if (!memberSearchIndex) { + createElem(doc, tag, 'member-search-index.js'); + } + if (!tagSearchIndex) { + createElem(doc, tag, 'tag-search-index.js'); + } + $(window).resize(function() { + $('.navPadding').css('padding-top', $('.fixedNav').css("height")); + }); +} + +function createElem(doc, tag, path) { + var script = doc.createElement(tag); + var scriptElement = doc.getElementsByTagName(tag)[0]; + script.src = pathtoroot + path; + scriptElement.parentNode.insertBefore(script, scriptElement); +} + +function show(type) { count = 0; - for (var key in methods) { + for (var key in data) { var row = document.getElementById(key); - if ((methods[key] & type) != 0) { + if ((data[key] & type) !== 0) { row.style.display = ''; row.className = (count++ % 2) ? rowColor : altColor; } @@ -13,8 +118,7 @@ function show(type) updateTabs(type); } -function updateTabs(type) -{ +function updateTabs(type) { for (var value in tabs) { var sNode = document.getElementById(tabs[value][0]); var spanNode = sNode.firstChild; @@ -28,3 +132,8 @@ function updateTabs(type) } } } + +function updateModuleFrame(pFrame, cFrame) { + top.packageFrame.location = pFrame; + top.classFrame.location = cFrame; +} diff --git a/docs/acf-bungee/search.js b/docs/acf-bungee/search.js new file mode 100644 index 00000000..b773531b --- /dev/null +++ b/docs/acf-bungee/search.js @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var noResult = {l: "No results found"}; +var catModules = "Modules"; +var catPackages = "Packages"; +var catTypes = "Types"; +var catMembers = "Members"; +var catSearchTags = "SearchTags"; +var highlight = "$&"; +var camelCaseRegexp = ""; +var secondaryMatcher = ""; +function getHighlightedText(item) { + var ccMatcher = new RegExp(camelCaseRegexp); + var label = item.replace(ccMatcher, highlight); + if (label === item) { + label = item.replace(secondaryMatcher, highlight); + } + return label; +} +function getURLPrefix(ui) { + var urlPrefix=""; + if (useModuleDirectories) { + var slash = "/"; + if (ui.item.category === catModules) { + return ui.item.l + slash; + } else if (ui.item.category === catPackages && ui.item.m) { + return ui.item.m + slash; + } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { + $.each(packageSearchIndex, function(index, item) { + if (ui.item.p == item.l) { + urlPrefix = item.m + slash; + } + }); + return urlPrefix; + } else { + return urlPrefix; + } + } + return urlPrefix; +} +var watermark = 'Search'; +$(function() { + $("#search").val(''); + $("#search").prop("disabled", false); + $("#reset").prop("disabled", false); + $("#search").val(watermark).addClass('watermark'); + $("#search").blur(function() { + if ($(this).val().length == 0) { + $(this).val(watermark).addClass('watermark'); + } + }); + $("#search").on('click keydown', function() { + if ($(this).val() == watermark) { + $(this).val('').removeClass('watermark'); + } + }); + $("#reset").click(function() { + $("#search").val(''); + $("#search").focus(); + }); + $("#search").focus(); + $("#search")[0].setSelectionRange(0, 0); +}); +$.widget("custom.catcomplete", $.ui.autocomplete, { + _create: function() { + this._super(); + this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)"); + }, + _renderMenu: function(ul, items) { + var rMenu = this, + currentCategory = ""; + rMenu.menu.bindings = $(); + $.each(items, function(index, item) { + var li; + if (item.l !== noResult.l && item.category !== currentCategory) { + ul.append("
  • " + item.category + "
  • "); + currentCategory = item.category; + } + li = rMenu._renderItemData(ul, item); + if (item.category) { + li.attr("aria-label", item.category + " : " + item.l); + li.attr("class", "resultItem"); + } else { + li.attr("aria-label", item.l); + li.attr("class", "resultItem"); + } + }); + }, + _renderItem: function(ul, item) { + var label = ""; + if (item.category === catModules) { + label = getHighlightedText(item.l); + } else if (item.category === catPackages) { + label = (item.m) + ? getHighlightedText(item.m + "/" + item.l) + : getHighlightedText(item.l); + } else if (item.category === catTypes) { + label = (item.p) + ? getHighlightedText(item.p + "." + item.l) + : getHighlightedText(item.l); + } else if (item.category === catMembers) { + label = getHighlightedText(item.p + "." + (item.c + "." + item.l)); + } else if (item.category === catSearchTags) { + label = getHighlightedText(item.l); + } else { + label = item.l; + } + var li = $("
  • ").appendTo(ul); + var div = $("
    ").appendTo(li); + if (item.category === catSearchTags) { + if (item.d) { + div.html(label + " (" + item.h + ")
    " + + item.d + "
    "); + } else { + div.html(label + " (" + item.h + ")"); + } + } else { + div.html(label); + } + return li; + } +}); +$(function() { + $("#search").catcomplete({ + minLength: 1, + delay: 100, + source: function(request, response) { + var result = new Array(); + var presult = new Array(); + var tresult = new Array(); + var mresult = new Array(); + var tgresult = new Array(); + var secondaryresult = new Array(); + var displayCount = 0; + var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i"); + camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)"); + var camelCaseMatcher = new RegExp("^" + camelCaseRegexp); + secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); + + // Return the nested innermost name from the specified object + function nestedName(e) { + return e.l.substring(e.l.lastIndexOf(".") + 1); + } + + function concatResults(a1, a2) { + a1 = a1.concat(a2); + a2.length = 0; + return a1; + } + + if (moduleSearchIndex) { + var mdleCount = 0; + $.each(moduleSearchIndex, function(index, item) { + item.category = catModules; + if (exactMatcher.test(item.l)) { + result.push(item); + mdleCount++; + } else if (camelCaseMatcher.test(item.l)) { + result.push(item); + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + displayCount = mdleCount; + result = concatResults(result, secondaryresult); + } + if (packageSearchIndex) { + var pCount = 0; + var pkg = ""; + $.each(packageSearchIndex, function(index, item) { + item.category = catPackages; + pkg = (item.m) + ? (item.m + "/" + item.l) + : item.l; + if (exactMatcher.test(item.l)) { + presult.push(item); + pCount++; + } else if (camelCaseMatcher.test(pkg)) { + presult.push(item); + } else if (secondaryMatcher.test(pkg)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(presult, secondaryresult)); + displayCount = (pCount > displayCount) ? pCount : displayCount; + } + if (typeSearchIndex) { + var tCount = 0; + $.each(typeSearchIndex, function(index, item) { + item.category = catTypes; + var s = nestedName(item); + if (exactMatcher.test(s)) { + tresult.push(item); + tCount++; + } else if (camelCaseMatcher.test(s)) { + tresult.push(item); + } else if (secondaryMatcher.test(item.p + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tresult, secondaryresult)); + displayCount = (tCount > displayCount) ? tCount : displayCount; + } + if (memberSearchIndex) { + var mCount = 0; + $.each(memberSearchIndex, function(index, item) { + item.category = catMembers; + var s = nestedName(item); + if (exactMatcher.test(s)) { + mresult.push(item); + mCount++; + } else if (camelCaseMatcher.test(s)) { + mresult.push(item); + } else if (secondaryMatcher.test(item.c + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(mresult, secondaryresult)); + displayCount = (mCount > displayCount) ? mCount : displayCount; + } + if (tagSearchIndex) { + var tgCount = 0; + $.each(tagSearchIndex, function(index, item) { + item.category = catSearchTags; + if (exactMatcher.test(item.l)) { + tgresult.push(item); + tgCount++; + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tgresult, secondaryresult)); + displayCount = (tgCount > displayCount) ? tgCount : displayCount; + } + displayCount = (displayCount > 500) ? displayCount : 500; + var counter = function() { + var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0}; + var f = function(item) { + count[item.category] += 1; + return (count[item.category] <= displayCount); + }; + return f; + }(); + response(result.filter(counter)); + }, + response: function(event, ui) { + if (!ui.content.length) { + ui.content.push(noResult); + } else { + $("#search").empty(); + } + }, + autoFocus: true, + position: { + collision: "flip" + }, + select: function(event, ui) { + if (ui.item.l !== noResult.l) { + var url = getURLPrefix(ui); + if (ui.item.category === catModules) { + if (useModuleDirectories) { + url += "module-summary.html"; + } else { + url = ui.item.l + "-summary.html"; + } + } else if (ui.item.category === catPackages) { + if (ui.item.url) { + url = ui.item.url; + } else { + url += ui.item.l.replace(/\./g, '/') + "/package-summary.html"; + } + } else if (ui.item.category === catTypes) { + if (ui.item.url) { + url = ui.item.url; + } else if (ui.item.p === "") { + url += ui.item.l + ".html"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; + } + } else if (ui.item.category === catMembers) { + if (ui.item.p === "") { + url += ui.item.c + ".html" + "#"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; + } + if (ui.item.url) { + url += ui.item.url; + } else { + url += ui.item.l; + } + } else if (ui.item.category === catSearchTags) { + url += ui.item.u; + } + if (top !== window) { + parent.classFrame.location = pathtoroot + url; + } else { + window.location.href = pathtoroot + url; + } + $("#search").focus(); + } + } + }); +}); diff --git a/docs/acf-bungee/src-html/co/aikar/commands/ACFBungeeListener.html b/docs/acf-bungee/src-html/co/aikar/commands/ACFBungeeListener.html index abfb4276..be139813 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/ACFBungeeListener.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/ACFBungeeListener.html @@ -1,48 +1,49 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import net.md_5.bungee.api.connection.ProxiedPlayer;
    -004import net.md_5.bungee.api.event.PlayerDisconnectEvent;
    -005import net.md_5.bungee.api.event.PostLoginEvent;
    -006import net.md_5.bungee.api.plugin.Listener;
    -007import net.md_5.bungee.api.plugin.Plugin;
    -008import net.md_5.bungee.event.EventHandler;
    -009
    -010import java.util.concurrent.TimeUnit;
    -011
    -012public class ACFBungeeListener implements Listener {
    -013
    -014    private final BungeeCommandManager manager;
    -015    private final Plugin plugin;
    -016
    -017    public ACFBungeeListener(BungeeCommandManager manager, Plugin plugin) {
    -018        this.manager = manager;
    -019        this.plugin = plugin;
    -020    }
    -021
    -022    @EventHandler
    -023    public void onPlayerJoin(PostLoginEvent loginEvent) {
    -024        ProxiedPlayer player = loginEvent.getPlayer();
    -025
    -026        //the client settings are sent after a successful login
    -027        Runnable task = () -> manager.readLocale(player);
    -028        plugin.getProxy().getScheduler().schedule(plugin, task, 1, TimeUnit.SECONDS);
    -029    }
    -030
    -031    @EventHandler
    -032    public void onDisconnect(PlayerDisconnectEvent disconnectEvent) {
    -033        //cleanup
    -034        ProxiedPlayer player = disconnectEvent.getPlayer();
    -035        manager.issuersLocale.remove(player.getUniqueId());
    -036    }
    -037}
    +
    001package co.aikar.commands;
    +002
    +003import net.md_5.bungee.api.connection.ProxiedPlayer;
    +004import net.md_5.bungee.api.event.PlayerDisconnectEvent;
    +005import net.md_5.bungee.api.event.PostLoginEvent;
    +006import net.md_5.bungee.api.plugin.Listener;
    +007import net.md_5.bungee.api.plugin.Plugin;
    +008import net.md_5.bungee.event.EventHandler;
    +009
    +010import java.util.concurrent.TimeUnit;
    +011
    +012public class ACFBungeeListener implements Listener {
    +013
    +014    private final BungeeCommandManager manager;
    +015    private final Plugin plugin;
    +016
    +017    public ACFBungeeListener(BungeeCommandManager manager, Plugin plugin) {
    +018        this.manager = manager;
    +019        this.plugin = plugin;
    +020    }
    +021
    +022    @EventHandler
    +023    public void onPlayerJoin(PostLoginEvent loginEvent) {
    +024        ProxiedPlayer player = loginEvent.getPlayer();
    +025
    +026        //the client settings are sent after a successful login
    +027        Runnable task = () -> manager.readLocale(player);
    +028        plugin.getProxy().getScheduler().schedule(plugin, task, 1, TimeUnit.SECONDS);
    +029    }
    +030
    +031    @EventHandler
    +032    public void onDisconnect(PlayerDisconnectEvent disconnectEvent) {
    +033        //cleanup
    +034        ProxiedPlayer player = disconnectEvent.getPlayer();
    +035        manager.issuersLocale.remove(player.getUniqueId());
    +036    }
    +037}
     
     
     
    @@ -105,5 +106,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/ACFBungeeUtil.html b/docs/acf-bungee/src-html/co/aikar/commands/ACFBungeeUtil.html index c33ec4f3..fa3edf25 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/ACFBungeeUtil.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/ACFBungeeUtil.html @@ -1,175 +1,176 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import net.md_5.bungee.api.ChatColor;
    -027import net.md_5.bungee.api.CommandSender;
    -028import net.md_5.bungee.api.ProxyServer;
    -029import net.md_5.bungee.api.connection.ProxiedPlayer;
    -030
    -031import java.util.ArrayList;
    -032import java.util.List;
    -033import java.util.regex.Pattern;
    -034import java.util.stream.Collectors;
    -035
    -036public class ACFBungeeUtil {
    -037
    -038    public static String color(String message) {
    -039        return ChatColor.translateAlternateColorCodes('&', message);
    -040    }
    -041
    -042    /**
    -043     * Move to Message Keys on the CommandIssuer
    -044     *
    -045     * @deprecated
    -046     */
    -047    @Deprecated
    -048    public static void sendMsg(CommandSender player, String message) {
    -049        message = color(message);
    -050        for (String msg : ACFPatterns.NEWLINE.split(message)) {
    -051            player.sendMessage(msg);
    -052        }
    -053    }
    -054
    -055    public static String removeColors(String msg) {
    -056        return ChatColor.stripColor(color(msg));
    -057    }
    -058
    -059    public static String replaceChatString(String message, String replace, String with) {
    -060        return replaceChatString(message, Pattern.compile(Pattern.quote(replace), Pattern.CASE_INSENSITIVE), with);
    -061    }
    -062
    -063    public static String replaceChatString(String message, Pattern replace, String with) {
    -064        final String[] split = replace.split(message + "1");
    -065
    -066        if (split.length < 2) {
    -067            return replace.matcher(message).replaceAll(with);
    -068        }
    -069        message = split[0];
    -070
    -071        for (int i = 1; i < split.length; i++) {
    -072            final String prev = getLastColors(message);
    -073            message += with + prev + split[i];
    -074        }
    -075        return message.substring(0, message.length() - 1);
    -076    }
    -077
    -078    //Imported from org.bukkit.ChatColor
    -079
    -080    public static final char COLOR_CHAR = '\u00A7';
    -081
    -082    public static String getLastColors(String input) {
    -083        StringBuilder result = new StringBuilder();
    -084        int length = input.length();
    -085
    -086        // Search backwards from the end as it is faster
    -087        for (int index = length - 1; index > -1; index--) {
    -088            char section = input.charAt(index);
    -089            if (section == COLOR_CHAR && index < length - 1) {
    -090                char c = input.charAt(index + 1);
    -091                ChatColor color = ChatColor.getByChar(c);
    -092
    -093                if (color != null) {
    -094                    result.insert(0, color.toString());
    -095
    -096                    // Once we find a color or reset we can stop searching
    -097                    if (isChatColorAColor(color) || color.equals(ChatColor.RESET)) {
    -098                        break;
    -099                    }
    -100                }
    -101            }
    -102        }
    -103        return result.toString();
    -104    }
    -105
    -106    public static boolean isChatColorAColor(ChatColor chatColor) {
    -107        return chatColor != ChatColor.MAGIC && chatColor != ChatColor.BOLD
    -108                && chatColor != ChatColor.STRIKETHROUGH && chatColor != ChatColor.UNDERLINE
    -109                && chatColor != ChatColor.ITALIC;
    -110    }
    -111
    -112
    -113    public static ProxiedPlayer findPlayerSmart(CommandIssuer issuer, String search) {
    -114        CommandSender requester = issuer.getIssuer();
    -115        String name = ACFUtil.replace(search, ":confirm", "");
    -116        if (!isValidName(name)) {
    -117            issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
    -118            return null;
    -119        }
    -120
    -121        List<ProxiedPlayer> matches = new ArrayList<>(ProxyServer.getInstance().matchPlayer(name));
    -122
    -123        if (matches.size() > 1) {
    -124            String allMatches = matches.stream().map(ProxiedPlayer::getName).collect(Collectors.joining(", "));
    -125            issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH,
    -126                    "{search}", name, "{all}", allMatches);
    -127            return null;
    -128        }
    -129
    -130        if (matches.isEmpty()) {
    -131            issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER,
    -132                    "{search}", name);
    -133            return null;
    -134        }
    -135
    -136        return matches.get(0);
    -137    }
    -138
    -139    /**
    -140     * Please move to the CommandIssuer version
    -141     *
    -142     * @deprecated
    -143     */
    -144    public static ProxiedPlayer findPlayerSmart(CommandSender requester, String search) {
    -145        CommandManager manager = CommandManager.getCurrentCommandManager();
    -146        if (manager != null) {
    -147            return findPlayerSmart(manager.getCommandIssuer(requester), search);
    -148        }
    -149        throw new IllegalStateException("You may not use the ACFBungeeUtil#findPlayerSmart(CommandSender) async to the command execution.");
    -150    }
    -151
    -152    public static boolean isValidName(String name) {
    -153        return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches();
    -154    }
    -155
    -156    public static <T> T validate(T object, String message, Object... values) {
    -157        if (object == null) {
    -158            throw new NullPointerException(String.format(message, values));
    -159        }
    -160        return object;
    -161    }
    -162
    -163
    -164}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import net.md_5.bungee.api.ChatColor;
    +027import net.md_5.bungee.api.CommandSender;
    +028import net.md_5.bungee.api.ProxyServer;
    +029import net.md_5.bungee.api.connection.ProxiedPlayer;
    +030
    +031import java.util.ArrayList;
    +032import java.util.List;
    +033import java.util.regex.Pattern;
    +034import java.util.stream.Collectors;
    +035
    +036public class ACFBungeeUtil {
    +037
    +038    public static String color(String message) {
    +039        return ChatColor.translateAlternateColorCodes('&', message);
    +040    }
    +041
    +042    /**
    +043     * Move to Message Keys on the CommandIssuer
    +044     *
    +045     * @deprecated
    +046     */
    +047    @Deprecated
    +048    public static void sendMsg(CommandSender player, String message) {
    +049        message = color(message);
    +050        for (String msg : ACFPatterns.NEWLINE.split(message)) {
    +051            player.sendMessage(msg);
    +052        }
    +053    }
    +054
    +055    public static String removeColors(String msg) {
    +056        return ChatColor.stripColor(color(msg));
    +057    }
    +058
    +059    public static String replaceChatString(String message, String replace, String with) {
    +060        return replaceChatString(message, Pattern.compile(Pattern.quote(replace), Pattern.CASE_INSENSITIVE), with);
    +061    }
    +062
    +063    public static String replaceChatString(String message, Pattern replace, String with) {
    +064        final String[] split = replace.split(message + "1");
    +065
    +066        if (split.length < 2) {
    +067            return replace.matcher(message).replaceAll(with);
    +068        }
    +069        message = split[0];
    +070
    +071        for (int i = 1; i < split.length; i++) {
    +072            final String prev = getLastColors(message);
    +073            message += with + prev + split[i];
    +074        }
    +075        return message.substring(0, message.length() - 1);
    +076    }
    +077
    +078    //Imported from org.bukkit.ChatColor
    +079
    +080    public static final char COLOR_CHAR = '\u00A7';
    +081
    +082    public static String getLastColors(String input) {
    +083        StringBuilder result = new StringBuilder();
    +084        int length = input.length();
    +085
    +086        // Search backwards from the end as it is faster
    +087        for (int index = length - 1; index > -1; index--) {
    +088            char section = input.charAt(index);
    +089            if (section == COLOR_CHAR && index < length - 1) {
    +090                char c = input.charAt(index + 1);
    +091                ChatColor color = ChatColor.getByChar(c);
    +092
    +093                if (color != null) {
    +094                    result.insert(0, color.toString());
    +095
    +096                    // Once we find a color or reset we can stop searching
    +097                    if (isChatColorAColor(color) || color.equals(ChatColor.RESET)) {
    +098                        break;
    +099                    }
    +100                }
    +101            }
    +102        }
    +103        return result.toString();
    +104    }
    +105
    +106    public static boolean isChatColorAColor(ChatColor chatColor) {
    +107        return chatColor != ChatColor.MAGIC && chatColor != ChatColor.BOLD
    +108                && chatColor != ChatColor.STRIKETHROUGH && chatColor != ChatColor.UNDERLINE
    +109                && chatColor != ChatColor.ITALIC;
    +110    }
    +111
    +112
    +113    public static ProxiedPlayer findPlayerSmart(CommandIssuer issuer, String search) {
    +114        CommandSender requester = issuer.getIssuer();
    +115        String name = ACFUtil.replace(search, ":confirm", "");
    +116        if (!isValidName(name)) {
    +117            issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
    +118            return null;
    +119        }
    +120
    +121        List<ProxiedPlayer> matches = new ArrayList<>(ProxyServer.getInstance().matchPlayer(name));
    +122
    +123        if (matches.size() > 1) {
    +124            String allMatches = matches.stream().map(ProxiedPlayer::getName).collect(Collectors.joining(", "));
    +125            issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH,
    +126                    "{search}", name, "{all}", allMatches);
    +127            return null;
    +128        }
    +129
    +130        if (matches.isEmpty()) {
    +131            issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER,
    +132                    "{search}", name);
    +133            return null;
    +134        }
    +135
    +136        return matches.get(0);
    +137    }
    +138
    +139    /**
    +140     * Please move to the CommandIssuer version
    +141     *
    +142     * @deprecated
    +143     */
    +144    public static ProxiedPlayer findPlayerSmart(CommandSender requester, String search) {
    +145        CommandManager manager = CommandManager.getCurrentCommandManager();
    +146        if (manager != null) {
    +147            return findPlayerSmart(manager.getCommandIssuer(requester), search);
    +148        }
    +149        throw new IllegalStateException("You may not use the ACFBungeeUtil#findPlayerSmart(CommandSender) async to the command execution.");
    +150    }
    +151
    +152    public static boolean isValidName(String name) {
    +153        return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches();
    +154    }
    +155
    +156    public static <T> T validate(T object, String message, Object... values) {
    +157        if (object == null) {
    +158            throw new NullPointerException(String.format(message, values));
    +159        }
    +160        return object;
    +161    }
    +162
    +163
    +164}
     
     
     
    @@ -232,5 +233,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandCompletionContext.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandCompletionContext.html index 129a3deb..e1630133 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandCompletionContext.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandCompletionContext.html @@ -1,53 +1,54 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import net.md_5.bungee.api.CommandSender;
    -027import net.md_5.bungee.api.connection.ProxiedPlayer;
    -028
    -029public class BungeeCommandCompletionContext extends CommandCompletionContext<BungeeCommandIssuer> {
    -030
    -031    BungeeCommandCompletionContext(RegisteredCommand command, BungeeCommandIssuer issuer, String input, String config, String[] args) {
    -032        super(command, issuer, input, config, args);
    -033    }
    -034
    -035    public CommandSender getSender() {
    -036        return this.getIssuer().getIssuer();
    -037    }
    -038
    -039    public ProxiedPlayer getPlayer() {
    -040        return this.issuer.getPlayer();
    -041    }
    -042}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import net.md_5.bungee.api.CommandSender;
    +027import net.md_5.bungee.api.connection.ProxiedPlayer;
    +028
    +029public class BungeeCommandCompletionContext extends CommandCompletionContext<BungeeCommandIssuer> {
    +030
    +031    BungeeCommandCompletionContext(RegisteredCommand command, BungeeCommandIssuer issuer, String input, String config, String[] args) {
    +032        super(command, issuer, input, config, args);
    +033    }
    +034
    +035    public CommandSender getSender() {
    +036        return this.getIssuer().getIssuer();
    +037    }
    +038
    +039    public ProxiedPlayer getPlayer() {
    +040        return this.issuer.getPlayer();
    +041    }
    +042}
     
     
     
    @@ -110,5 +111,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandCompletions.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandCompletions.html index 380b28e1..ab800fcf 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandCompletions.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandCompletions.html @@ -1,85 +1,86 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
    -027import net.md_5.bungee.api.ChatColor;
    -028import net.md_5.bungee.api.CommandSender;
    -029import net.md_5.bungee.api.ProxyServer;
    -030import net.md_5.bungee.api.connection.ProxiedPlayer;
    -031
    -032import java.util.ArrayList;
    -033import java.util.Arrays;
    -034import java.util.Set;
    -035import java.util.stream.Collectors;
    -036import java.util.stream.Stream;
    -037
    -038public class BungeeCommandCompletions extends CommandCompletions<BungeeCommandCompletionContext> {
    -039
    -040    public BungeeCommandCompletions(CommandManager manager) {
    -041        super(manager);
    -042        registerAsyncCompletion("chatcolors", c -> {
    -043            Stream<ChatColor> colors = Stream.of(ChatColor.values());
    -044            if (c.hasConfig("colorsonly")) {
    -045                colors = colors.filter(color -> color.ordinal() <= 0xF);
    -046            }
    -047            String filter = c.getConfig("filter");
    -048            if (filter != null) {
    -049                Set<String> filters = Arrays.stream(ACFPatterns.COLON.split(filter))
    -050                        .map(ACFUtil::simplifyString).collect(Collectors.toSet());
    -051
    -052                colors = colors.filter(color -> filters.contains(ACFUtil.simplifyString(color.name())));
    -053            }
    -054
    -055            return colors.map(color -> ACFUtil.simplifyString(color.name())).collect(Collectors.toList());
    -056        });
    -057        registerCompletion("players", c -> {
    -058            CommandSender sender = c.getSender();
    -059            ACFBungeeUtil.validate(sender, "Sender cannot be null");
    -060            String input = c.getInput();
    -061
    -062            ArrayList<String> matchedPlayers = new ArrayList<>();
    -063            for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
    -064                String name = player.getName();
    -065                if (ApacheCommonsLangUtil.startsWithIgnoreCase(name, input)) {
    -066                    matchedPlayers.add(name);
    -067                }
    -068            }
    -069
    -070            matchedPlayers.sort(String.CASE_INSENSITIVE_ORDER);
    -071            return matchedPlayers;
    -072        });
    -073    }
    -074}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
    +027import net.md_5.bungee.api.ChatColor;
    +028import net.md_5.bungee.api.CommandSender;
    +029import net.md_5.bungee.api.ProxyServer;
    +030import net.md_5.bungee.api.connection.ProxiedPlayer;
    +031
    +032import java.util.ArrayList;
    +033import java.util.Arrays;
    +034import java.util.Set;
    +035import java.util.stream.Collectors;
    +036import java.util.stream.Stream;
    +037
    +038public class BungeeCommandCompletions extends CommandCompletions<BungeeCommandCompletionContext> {
    +039
    +040    public BungeeCommandCompletions(CommandManager manager) {
    +041        super(manager);
    +042        registerAsyncCompletion("chatcolors", c -> {
    +043            Stream<ChatColor> colors = Stream.of(ChatColor.values());
    +044            if (c.hasConfig("colorsonly")) {
    +045                colors = colors.filter(color -> color.ordinal() <= 0xF);
    +046            }
    +047            String filter = c.getConfig("filter");
    +048            if (filter != null) {
    +049                Set<String> filters = Arrays.stream(ACFPatterns.COLON.split(filter))
    +050                        .map(ACFUtil::simplifyString).collect(Collectors.toSet());
    +051
    +052                colors = colors.filter(color -> filters.contains(ACFUtil.simplifyString(color.name())));
    +053            }
    +054
    +055            return colors.map(color -> ACFUtil.simplifyString(color.name())).collect(Collectors.toList());
    +056        });
    +057        registerCompletion("players", c -> {
    +058            CommandSender sender = c.getSender();
    +059            ACFBungeeUtil.validate(sender, "Sender cannot be null");
    +060            String input = c.getInput();
    +061
    +062            ArrayList<String> matchedPlayers = new ArrayList<>();
    +063            for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
    +064                String name = player.getName();
    +065                if (ApacheCommonsLangUtil.startsWithIgnoreCase(name, input)) {
    +066                    matchedPlayers.add(name);
    +067                }
    +068            }
    +069
    +070            matchedPlayers.sort(String.CASE_INSENSITIVE_ORDER);
    +071            return matchedPlayers;
    +072        });
    +073    }
    +074}
     
     
     
    @@ -142,5 +143,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandContexts.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandContexts.html index a76fda0a..e9191b2d 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandContexts.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandContexts.html @@ -1,102 +1,103 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026
    -027import co.aikar.commands.annotation.Optional;
    -028import co.aikar.commands.bungee.contexts.OnlinePlayer;
    -029import net.md_5.bungee.api.ChatColor;
    -030import net.md_5.bungee.api.CommandSender;
    -031import net.md_5.bungee.api.connection.ProxiedPlayer;
    -032import org.jetbrains.annotations.Nullable;
    -033
    -034import java.util.stream.Collectors;
    -035import java.util.stream.Stream;
    -036
    -037public class BungeeCommandContexts extends CommandContexts<BungeeCommandExecutionContext> {
    -038
    -039    BungeeCommandContexts(CommandManager manager) {
    -040        super(manager);
    -041        registerContext(OnlinePlayer.class, this::getOnlinePlayer);
    -042        registerContext(co.aikar.commands.contexts.OnlineProxiedPlayer.class, c -> {
    -043            OnlinePlayer onlinePlayer = getOnlinePlayer(c);
    -044            return onlinePlayer != null ? new co.aikar.commands.contexts.OnlineProxiedPlayer(onlinePlayer.getPlayer()) : null;
    -045        });
    -046        registerIssuerAwareContext(CommandSender.class, BungeeCommandExecutionContext::getSender);
    -047        registerIssuerAwareContext(ProxiedPlayer.class, (c) -> {
    -048            ProxiedPlayer proxiedPlayer = c.getSender() instanceof ProxiedPlayer ? (ProxiedPlayer) c.getSender() : null;
    -049            if (proxiedPlayer == null && !c.hasAnnotation(Optional.class)) {
    -050                throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
    -051            }
    -052            return proxiedPlayer;
    -053        });
    -054
    -055        registerContext(ChatColor.class, c -> {
    -056            String first = c.popFirstArg();
    -057            Stream<ChatColor> colors = Stream.of(ChatColor.values());
    -058            if (c.hasFlag("colorsonly")) {
    -059                colors = colors.filter(color -> color.ordinal() <= 0xF);
    -060            }
    -061            String filter = c.getFlagValue("filter", (String) null);
    -062            if (filter != null) {
    -063                filter = ACFUtil.simplifyString(filter);
    -064                String finalFilter = filter;
    -065                colors = colors.filter(color -> finalFilter.equals(ACFUtil.simplifyString(color.name())));
    -066            }
    -067
    -068            ChatColor match = ACFUtil.simpleMatch(ChatColor.class, first);
    -069            if (match == null) {
    -070                String valid = colors
    -071                        .map(color -> "<c2>" + ACFUtil.simplifyString(color.name()) + "</c2>")
    -072                        .collect(Collectors.joining("<c1>,</c1> "));
    -073
    -074                throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
    -075            }
    -076            return match;
    -077        });
    -078    }
    -079
    -080    @Nullable
    -081    private co.aikar.commands.contexts.OnlineProxiedPlayer getOnlinePlayer(BungeeCommandExecutionContext c) throws InvalidCommandArgument {
    -082        ProxiedPlayer proxiedPlayer = ACFBungeeUtil.findPlayerSmart(c.getIssuer(), c.popFirstArg());
    -083        if (proxiedPlayer == null) {
    -084            if (c.hasAnnotation(Optional.class)) {
    -085                return null;
    -086            }
    -087            throw new InvalidCommandArgument(false);
    -088        }
    -089        return new co.aikar.commands.contexts.OnlineProxiedPlayer(proxiedPlayer);
    -090    }
    -091}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026
    +027import co.aikar.commands.annotation.Optional;
    +028import co.aikar.commands.bungee.contexts.OnlinePlayer;
    +029import net.md_5.bungee.api.ChatColor;
    +030import net.md_5.bungee.api.CommandSender;
    +031import net.md_5.bungee.api.connection.ProxiedPlayer;
    +032import org.jetbrains.annotations.Nullable;
    +033
    +034import java.util.stream.Collectors;
    +035import java.util.stream.Stream;
    +036
    +037public class BungeeCommandContexts extends CommandContexts<BungeeCommandExecutionContext> {
    +038
    +039    BungeeCommandContexts(CommandManager manager) {
    +040        super(manager);
    +041        registerContext(OnlinePlayer.class, this::getOnlinePlayer);
    +042        registerContext(co.aikar.commands.contexts.OnlineProxiedPlayer.class, c -> {
    +043            OnlinePlayer onlinePlayer = getOnlinePlayer(c);
    +044            return onlinePlayer != null ? new co.aikar.commands.contexts.OnlineProxiedPlayer(onlinePlayer.getPlayer()) : null;
    +045        });
    +046        registerIssuerAwareContext(CommandSender.class, BungeeCommandExecutionContext::getSender);
    +047        registerIssuerAwareContext(ProxiedPlayer.class, (c) -> {
    +048            ProxiedPlayer proxiedPlayer = c.getSender() instanceof ProxiedPlayer ? (ProxiedPlayer) c.getSender() : null;
    +049            if (proxiedPlayer == null && !c.hasAnnotation(Optional.class)) {
    +050                throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
    +051            }
    +052            return proxiedPlayer;
    +053        });
    +054
    +055        registerContext(ChatColor.class, c -> {
    +056            String first = c.popFirstArg();
    +057            Stream<ChatColor> colors = Stream.of(ChatColor.values());
    +058            if (c.hasFlag("colorsonly")) {
    +059                colors = colors.filter(color -> color.ordinal() <= 0xF);
    +060            }
    +061            String filter = c.getFlagValue("filter", (String) null);
    +062            if (filter != null) {
    +063                filter = ACFUtil.simplifyString(filter);
    +064                String finalFilter = filter;
    +065                colors = colors.filter(color -> finalFilter.equals(ACFUtil.simplifyString(color.name())));
    +066            }
    +067
    +068            ChatColor match = ACFUtil.simpleMatch(ChatColor.class, first);
    +069            if (match == null) {
    +070                String valid = colors
    +071                        .map(color -> "<c2>" + ACFUtil.simplifyString(color.name()) + "</c2>")
    +072                        .collect(Collectors.joining("<c1>,</c1> "));
    +073
    +074                throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
    +075            }
    +076            return match;
    +077        });
    +078    }
    +079
    +080    @Nullable
    +081    private co.aikar.commands.contexts.OnlineProxiedPlayer getOnlinePlayer(BungeeCommandExecutionContext c) throws InvalidCommandArgument {
    +082        ProxiedPlayer proxiedPlayer = ACFBungeeUtil.findPlayerSmart(c.getIssuer(), c.popFirstArg());
    +083        if (proxiedPlayer == null) {
    +084            if (c.hasAnnotation(Optional.class)) {
    +085                return null;
    +086            }
    +087            throw new InvalidCommandArgument(false);
    +088        }
    +089        return new co.aikar.commands.contexts.OnlineProxiedPlayer(proxiedPlayer);
    +090    }
    +091}
     
     
     
    @@ -159,5 +160,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandExecutionContext.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandExecutionContext.html index 3c0744ba..1bab27df 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandExecutionContext.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandExecutionContext.html @@ -1,56 +1,57 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import net.md_5.bungee.api.CommandSender;
    -027import net.md_5.bungee.api.connection.ProxiedPlayer;
    -028
    -029import java.util.List;
    -030import java.util.Map;
    -031
    -032public class BungeeCommandExecutionContext extends CommandExecutionContext<BungeeCommandExecutionContext, BungeeCommandIssuer> {
    -033
    -034    BungeeCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, BungeeCommandIssuer sender, List<String> args, int index, Map<String, Object> passedArgs) {
    -035        super(cmd, param, sender, args, index, passedArgs);
    -036    }
    -037
    -038    public CommandSender getSender() {
    -039        return this.issuer.getIssuer();
    -040    }
    -041
    -042    public ProxiedPlayer getPlayer() {
    -043        return this.issuer.getPlayer();
    -044    }
    -045}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import net.md_5.bungee.api.CommandSender;
    +027import net.md_5.bungee.api.connection.ProxiedPlayer;
    +028
    +029import java.util.List;
    +030import java.util.Map;
    +031
    +032public class BungeeCommandExecutionContext extends CommandExecutionContext<BungeeCommandExecutionContext, BungeeCommandIssuer> {
    +033
    +034    BungeeCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, BungeeCommandIssuer sender, List<String> args, int index, Map<String, Object> passedArgs) {
    +035        super(cmd, param, sender, args, index, passedArgs);
    +036    }
    +037
    +038    public CommandSender getSender() {
    +039        return this.issuer.getIssuer();
    +040    }
    +041
    +042    public ProxiedPlayer getPlayer() {
    +043        return this.issuer.getPlayer();
    +044    }
    +045}
     
     
     
    @@ -113,5 +114,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandIssuer.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandIssuer.html index 968bed8a..1c87c300 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandIssuer.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandIssuer.html @@ -1,107 +1,108 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import net.md_5.bungee.api.CommandSender;
    -027import net.md_5.bungee.api.connection.ProxiedPlayer;
    -028import org.jetbrains.annotations.NotNull;
    -029
    -030import java.nio.charset.StandardCharsets;
    -031import java.util.Objects;
    -032import java.util.UUID;
    -033
    -034public class BungeeCommandIssuer implements CommandIssuer {
    -035    private final BungeeCommandManager manager;
    -036    private final CommandSender sender;
    -037
    -038    BungeeCommandIssuer(BungeeCommandManager manager, CommandSender sender) {
    -039        this.manager = manager;
    -040        this.sender = sender;
    -041    }
    -042
    -043
    -044    @Override
    -045    public CommandSender getIssuer() {
    -046        return sender;
    -047    }
    -048
    -049    public ProxiedPlayer getPlayer() {
    -050        return isPlayer() ? (ProxiedPlayer) sender : null;
    -051    }
    -052
    -053    @Override
    -054    public CommandManager getManager() {
    -055        return manager;
    -056    }
    -057
    -058    @Override
    -059    public boolean isPlayer() {
    -060        return sender instanceof ProxiedPlayer;
    -061    }
    -062
    -063    @Override
    -064    public @NotNull UUID getUniqueId() {
    -065        if (isPlayer()) {
    -066            return ((ProxiedPlayer) sender).getUniqueId();
    -067        }
    -068
    -069        //generate a unique id based of the name (like for the console command sender)
    -070        return UUID.nameUUIDFromBytes(sender.getName().getBytes(StandardCharsets.UTF_8));
    -071    }
    -072
    -073    @Override
    -074    public void sendMessageInternal(String message) {
    -075        sender.sendMessage(ACFBungeeUtil.color(message));
    -076    }
    -077
    -078    @Override
    -079    public boolean hasPermission(String name) {
    -080        return sender.hasPermission(name);
    -081    }
    -082
    -083
    -084    @Override
    -085    public boolean equals(Object o) {
    -086        if (this == o) return true;
    -087        if (o == null || getClass() != o.getClass()) return false;
    -088        BungeeCommandIssuer that = (BungeeCommandIssuer) o;
    -089        return Objects.equals(sender, that.sender);
    -090    }
    -091
    -092    @Override
    -093    public int hashCode() {
    -094        return Objects.hash(sender);
    -095    }
    -096}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import net.md_5.bungee.api.CommandSender;
    +027import net.md_5.bungee.api.connection.ProxiedPlayer;
    +028import org.jetbrains.annotations.NotNull;
    +029
    +030import java.nio.charset.StandardCharsets;
    +031import java.util.Objects;
    +032import java.util.UUID;
    +033
    +034public class BungeeCommandIssuer implements CommandIssuer {
    +035    private final BungeeCommandManager manager;
    +036    private final CommandSender sender;
    +037
    +038    BungeeCommandIssuer(BungeeCommandManager manager, CommandSender sender) {
    +039        this.manager = manager;
    +040        this.sender = sender;
    +041    }
    +042
    +043
    +044    @Override
    +045    public CommandSender getIssuer() {
    +046        return sender;
    +047    }
    +048
    +049    public ProxiedPlayer getPlayer() {
    +050        return isPlayer() ? (ProxiedPlayer) sender : null;
    +051    }
    +052
    +053    @Override
    +054    public CommandManager getManager() {
    +055        return manager;
    +056    }
    +057
    +058    @Override
    +059    public boolean isPlayer() {
    +060        return sender instanceof ProxiedPlayer;
    +061    }
    +062
    +063    @Override
    +064    public @NotNull UUID getUniqueId() {
    +065        if (isPlayer()) {
    +066            return ((ProxiedPlayer) sender).getUniqueId();
    +067        }
    +068
    +069        //generate a unique id based of the name (like for the console command sender)
    +070        return UUID.nameUUIDFromBytes(sender.getName().getBytes(StandardCharsets.UTF_8));
    +071    }
    +072
    +073    @Override
    +074    public void sendMessageInternal(String message) {
    +075        sender.sendMessage(ACFBungeeUtil.color(message));
    +076    }
    +077
    +078    @Override
    +079    public boolean hasPermission(String name) {
    +080        return sender.hasPermission(name);
    +081    }
    +082
    +083
    +084    @Override
    +085    public boolean equals(Object o) {
    +086        if (this == o) return true;
    +087        if (o == null || getClass() != o.getClass()) return false;
    +088        BungeeCommandIssuer that = (BungeeCommandIssuer) o;
    +089        return Objects.equals(sender, that.sender);
    +090    }
    +091
    +092    @Override
    +093    public int hashCode() {
    +094        return Objects.hash(sender);
    +095    }
    +096}
     
     
     
    @@ -164,5 +165,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandManager.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandManager.html index 0c849a70..a7f19405 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandManager.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeCommandManager.html @@ -1,234 +1,235 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    -027import net.md_5.bungee.api.ChatColor;
    -028import net.md_5.bungee.api.CommandSender;
    -029import net.md_5.bungee.api.ProxyServer;
    -030import net.md_5.bungee.api.connection.ProxiedPlayer;
    -031import net.md_5.bungee.api.plugin.Plugin;
    -032
    -033import java.lang.reflect.Method;
    -034import java.util.Collection;
    -035import java.util.Collections;
    -036import java.util.HashMap;
    -037import java.util.List;
    -038import java.util.Locale;
    -039import java.util.Map;
    -040import java.util.concurrent.TimeUnit;
    -041import java.util.logging.Level;
    -042import java.util.logging.Logger;
    -043
    -044public class BungeeCommandManager extends CommandManager<
    -045        CommandSender,
    -046        BungeeCommandIssuer,
    -047        ChatColor,
    -048        BungeeMessageFormatter,
    -049        BungeeCommandExecutionContext,
    -050        BungeeConditionContext
    -051    > {
    -052
    -053    protected final Plugin plugin;
    -054    protected Map<String, BungeeRootCommand> registeredCommands = new HashMap<>();
    -055    protected BungeeCommandContexts contexts;
    -056    protected BungeeCommandCompletions completions;
    -057    protected BungeeLocales locales;
    -058
    -059    public BungeeCommandManager(Plugin plugin) {
    -060        this.plugin = plugin;
    -061        this.formatters.put(MessageType.ERROR, defaultFormatter = new BungeeMessageFormatter(ChatColor.RED, ChatColor.YELLOW, ChatColor.RED));
    -062        this.formatters.put(MessageType.SYNTAX, new BungeeMessageFormatter(ChatColor.YELLOW, ChatColor.GREEN, ChatColor.WHITE));
    -063        this.formatters.put(MessageType.INFO, new BungeeMessageFormatter(ChatColor.BLUE, ChatColor.DARK_GREEN, ChatColor.GREEN));
    -064        this.formatters.put(MessageType.HELP, new BungeeMessageFormatter(ChatColor.AQUA, ChatColor.GREEN, ChatColor.YELLOW));
    -065
    -066        getLocales(); // auto load locales
    -067
    -068        plugin.getProxy().getPluginManager().registerListener(plugin, new ACFBungeeListener(this, plugin));
    -069
    -070        //BungeeCord has no event for listening for client setting changes
    -071        plugin.getProxy().getScheduler().schedule(plugin, () -> {
    -072            ProxyServer.getInstance().getPlayers().forEach(this::readLocale);
    -073        }, 5, 5, TimeUnit.SECONDS);
    -074
    -075        // TODO more default dependencies for bungee
    -076        registerDependency(plugin.getClass(), plugin);
    -077        registerDependency(Plugin.class, plugin);
    -078    }
    -079
    -080    public Plugin getPlugin() {
    -081        return this.plugin;
    -082    }
    -083
    -084    @Override
    -085    public synchronized CommandContexts<BungeeCommandExecutionContext> getCommandContexts() {
    -086        if (this.contexts == null) {
    -087            this.contexts = new BungeeCommandContexts(this);
    -088        }
    -089        return contexts;
    -090    }
    -091
    -092    @Override
    -093    public synchronized CommandCompletions<BungeeCommandCompletionContext> getCommandCompletions() {
    -094        if (this.completions == null) {
    -095            this.completions = new BungeeCommandCompletions(this);
    -096        }
    -097        return completions;
    -098    }
    -099
    -100    @Override
    -101    public BungeeLocales getLocales() {
    -102        if (this.locales == null) {
    -103            this.locales = new BungeeLocales(this);
    -104            this.locales.loadLanguages();
    -105        }
    -106        return locales;
    -107    }
    -108
    -109    public void readLocale(ProxiedPlayer player) {
    -110        if (!player.isConnected()) {
    -111            return;
    -112        }
    -113
    -114        //This can be null if we didn't received a settings packet
    -115        Locale locale = player.getLocale();
    -116        if (locale != null) {
    -117            setIssuerLocale(player, player.getLocale());
    -118        }
    -119    }
    -120
    -121    @Override
    -122    public void registerCommand(BaseCommand command) {
    -123        command.onRegister(this);
    -124        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    -125            String commandName = entry.getKey().toLowerCase();
    -126            BungeeRootCommand bungeeCommand = (BungeeRootCommand) entry.getValue();
    -127            if (!bungeeCommand.isRegistered) {
    -128                this.plugin.getProxy().getPluginManager().registerCommand(this.plugin, bungeeCommand);
    -129            }
    -130            bungeeCommand.isRegistered = true;
    -131            registeredCommands.put(commandName, bungeeCommand);
    -132        }
    -133    }
    -134
    -135    public void unregisterCommand(BaseCommand command) {
    -136        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    -137            String commandName = entry.getKey().toLowerCase();
    -138            BungeeRootCommand bungeeCommand = (BungeeRootCommand) entry.getValue();
    -139            bungeeCommand.getSubCommands().values().removeAll(command.subCommands.values());
    -140            if (bungeeCommand.getSubCommands().isEmpty() && bungeeCommand.isRegistered)  {
    -141                unregisterCommand(bungeeCommand);
    -142                bungeeCommand.isRegistered = false;
    -143                registeredCommands.remove(commandName);
    -144            }
    -145        }
    -146    }
    -147
    -148    public void unregisterCommand(BungeeRootCommand command) {
    -149        this.plugin.getProxy().getPluginManager().unregisterCommand(command);
    -150    }
    -151
    -152    public void unregisterCommands() {
    -153        for (Map.Entry<String, BungeeRootCommand> entry : registeredCommands.entrySet()) {
    -154            unregisterCommand(entry.getValue());
    -155        }
    -156    }
    -157
    -158    @Override
    -159    public boolean hasRegisteredCommands() {
    -160        return !registeredCommands.isEmpty();
    -161    }
    -162
    -163    @Override
    -164    public boolean isCommandIssuer(Class<?> aClass) {
    -165        return CommandSender.class.isAssignableFrom(aClass);
    -166    }
    -167
    -168    @Override
    -169    public BungeeCommandIssuer getCommandIssuer(Object issuer) {
    -170        if (!(issuer instanceof CommandSender)) {
    -171            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
    -172        }
    -173        return new BungeeCommandIssuer(this, (CommandSender) issuer);
    -174    }
    -175
    -176    @Override
    -177    public RootCommand createRootCommand(String cmd) {
    -178        return new BungeeRootCommand(this, cmd);
    -179    }
    -180    
    -181    @Override
    -182    public Collection<RootCommand> getRegisteredRootCommands() {
    -183        return Collections.unmodifiableCollection(registeredCommands.values());
    -184    }
    -185
    -186    @Override
    -187    public BungeeCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
    -188        return new BungeeCommandExecutionContext(command, parameter, (BungeeCommandIssuer) sender, args, i, passedArgs);
    -189    }
    -190
    -191    @Override
    -192    public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
    -193        return new BungeeCommandCompletionContext(command, (BungeeCommandIssuer) sender, input, config, args);
    -194    }
    -195
    -196    @Override
    -197    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
    -198        return new RegisteredCommand(command, cmdName, method, prefSubCommand);
    -199    }
    -200
    -201    @Override
    -202    public BungeeConditionContext createConditionContext(CommandIssuer issuer, String config) {
    -203        return new BungeeConditionContext((BungeeCommandIssuer) issuer, config);
    -204    }
    -205
    -206    @Override
    -207    public void log(LogLevel level, String message, Throwable throwable) {
    -208        Logger logger = this.plugin.getLogger();
    -209        Level logLevel = level == LogLevel.INFO ? Level.INFO : Level.SEVERE;
    -210        logger.log(logLevel, LogLevel.LOG_PREFIX + message);
    -211        if (throwable != null) {
    -212            for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    -213                logger.log(logLevel, LogLevel.LOG_PREFIX + line);
    -214            }
    -215        }
    -216    }
    -217
    -218
    -219    @Override
    -220    public String getCommandPrefix(CommandIssuer issuer) {
    -221        return issuer.isPlayer() ? "/" : "";
    -222    }
    -223}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    +027import net.md_5.bungee.api.ChatColor;
    +028import net.md_5.bungee.api.CommandSender;
    +029import net.md_5.bungee.api.ProxyServer;
    +030import net.md_5.bungee.api.connection.ProxiedPlayer;
    +031import net.md_5.bungee.api.plugin.Plugin;
    +032
    +033import java.lang.reflect.Method;
    +034import java.util.Collection;
    +035import java.util.Collections;
    +036import java.util.HashMap;
    +037import java.util.List;
    +038import java.util.Locale;
    +039import java.util.Map;
    +040import java.util.concurrent.TimeUnit;
    +041import java.util.logging.Level;
    +042import java.util.logging.Logger;
    +043
    +044public class BungeeCommandManager extends CommandManager<
    +045        CommandSender,
    +046        BungeeCommandIssuer,
    +047        ChatColor,
    +048        BungeeMessageFormatter,
    +049        BungeeCommandExecutionContext,
    +050        BungeeConditionContext
    +051    > {
    +052
    +053    protected final Plugin plugin;
    +054    protected Map<String, BungeeRootCommand> registeredCommands = new HashMap<>();
    +055    protected BungeeCommandContexts contexts;
    +056    protected BungeeCommandCompletions completions;
    +057    protected BungeeLocales locales;
    +058
    +059    public BungeeCommandManager(Plugin plugin) {
    +060        this.plugin = plugin;
    +061        this.formatters.put(MessageType.ERROR, defaultFormatter = new BungeeMessageFormatter(ChatColor.RED, ChatColor.YELLOW, ChatColor.RED));
    +062        this.formatters.put(MessageType.SYNTAX, new BungeeMessageFormatter(ChatColor.YELLOW, ChatColor.GREEN, ChatColor.WHITE));
    +063        this.formatters.put(MessageType.INFO, new BungeeMessageFormatter(ChatColor.BLUE, ChatColor.DARK_GREEN, ChatColor.GREEN));
    +064        this.formatters.put(MessageType.HELP, new BungeeMessageFormatter(ChatColor.AQUA, ChatColor.GREEN, ChatColor.YELLOW));
    +065
    +066        getLocales(); // auto load locales
    +067
    +068        plugin.getProxy().getPluginManager().registerListener(plugin, new ACFBungeeListener(this, plugin));
    +069
    +070        //BungeeCord has no event for listening for client setting changes
    +071        plugin.getProxy().getScheduler().schedule(plugin, () -> {
    +072            ProxyServer.getInstance().getPlayers().forEach(this::readLocale);
    +073        }, 5, 5, TimeUnit.SECONDS);
    +074
    +075        // TODO more default dependencies for bungee
    +076        registerDependency(plugin.getClass(), plugin);
    +077        registerDependency(Plugin.class, plugin);
    +078    }
    +079
    +080    public Plugin getPlugin() {
    +081        return this.plugin;
    +082    }
    +083
    +084    @Override
    +085    public synchronized CommandContexts<BungeeCommandExecutionContext> getCommandContexts() {
    +086        if (this.contexts == null) {
    +087            this.contexts = new BungeeCommandContexts(this);
    +088        }
    +089        return contexts;
    +090    }
    +091
    +092    @Override
    +093    public synchronized CommandCompletions<BungeeCommandCompletionContext> getCommandCompletions() {
    +094        if (this.completions == null) {
    +095            this.completions = new BungeeCommandCompletions(this);
    +096        }
    +097        return completions;
    +098    }
    +099
    +100    @Override
    +101    public BungeeLocales getLocales() {
    +102        if (this.locales == null) {
    +103            this.locales = new BungeeLocales(this);
    +104            this.locales.loadLanguages();
    +105        }
    +106        return locales;
    +107    }
    +108
    +109    public void readLocale(ProxiedPlayer player) {
    +110        if (!player.isConnected()) {
    +111            return;
    +112        }
    +113
    +114        //This can be null if we didn't received a settings packet
    +115        Locale locale = player.getLocale();
    +116        if (locale != null) {
    +117            setIssuerLocale(player, player.getLocale());
    +118        }
    +119    }
    +120
    +121    @Override
    +122    public void registerCommand(BaseCommand command) {
    +123        command.onRegister(this);
    +124        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    +125            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
    +126            BungeeRootCommand bungeeCommand = (BungeeRootCommand) entry.getValue();
    +127            if (!bungeeCommand.isRegistered) {
    +128                this.plugin.getProxy().getPluginManager().registerCommand(this.plugin, bungeeCommand);
    +129            }
    +130            bungeeCommand.isRegistered = true;
    +131            registeredCommands.put(commandName, bungeeCommand);
    +132        }
    +133    }
    +134
    +135    public void unregisterCommand(BaseCommand command) {
    +136        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    +137            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
    +138            BungeeRootCommand bungeeCommand = (BungeeRootCommand) entry.getValue();
    +139            bungeeCommand.getSubCommands().values().removeAll(command.subCommands.values());
    +140            if (bungeeCommand.getSubCommands().isEmpty() && bungeeCommand.isRegistered)  {
    +141                unregisterCommand(bungeeCommand);
    +142                bungeeCommand.isRegistered = false;
    +143                registeredCommands.remove(commandName);
    +144            }
    +145        }
    +146    }
    +147
    +148    public void unregisterCommand(BungeeRootCommand command) {
    +149        this.plugin.getProxy().getPluginManager().unregisterCommand(command);
    +150    }
    +151
    +152    public void unregisterCommands() {
    +153        for (Map.Entry<String, BungeeRootCommand> entry : registeredCommands.entrySet()) {
    +154            unregisterCommand(entry.getValue());
    +155        }
    +156    }
    +157
    +158    @Override
    +159    public boolean hasRegisteredCommands() {
    +160        return !registeredCommands.isEmpty();
    +161    }
    +162
    +163    @Override
    +164    public boolean isCommandIssuer(Class<?> aClass) {
    +165        return CommandSender.class.isAssignableFrom(aClass);
    +166    }
    +167
    +168    @Override
    +169    public BungeeCommandIssuer getCommandIssuer(Object issuer) {
    +170        if (!(issuer instanceof CommandSender)) {
    +171            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
    +172        }
    +173        return new BungeeCommandIssuer(this, (CommandSender) issuer);
    +174    }
    +175
    +176    @Override
    +177    public RootCommand createRootCommand(String cmd) {
    +178        return new BungeeRootCommand(this, cmd);
    +179    }
    +180    
    +181    @Override
    +182    public Collection<RootCommand> getRegisteredRootCommands() {
    +183        return Collections.unmodifiableCollection(registeredCommands.values());
    +184    }
    +185
    +186    @Override
    +187    public BungeeCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
    +188        return new BungeeCommandExecutionContext(command, parameter, (BungeeCommandIssuer) sender, args, i, passedArgs);
    +189    }
    +190
    +191    @Override
    +192    public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
    +193        return new BungeeCommandCompletionContext(command, (BungeeCommandIssuer) sender, input, config, args);
    +194    }
    +195
    +196    @Override
    +197    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
    +198        return new RegisteredCommand(command, cmdName, method, prefSubCommand);
    +199    }
    +200
    +201    @Override
    +202    public BungeeConditionContext createConditionContext(CommandIssuer issuer, String config) {
    +203        return new BungeeConditionContext((BungeeCommandIssuer) issuer, config);
    +204    }
    +205
    +206    @Override
    +207    public void log(LogLevel level, String message, Throwable throwable) {
    +208        Logger logger = this.plugin.getLogger();
    +209        Level logLevel = level == LogLevel.INFO ? Level.INFO : Level.SEVERE;
    +210        logger.log(logLevel, LogLevel.LOG_PREFIX + message);
    +211        if (throwable != null) {
    +212            for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    +213                logger.log(logLevel, LogLevel.LOG_PREFIX + line);
    +214            }
    +215        }
    +216    }
    +217
    +218
    +219    @Override
    +220    public String getCommandPrefix(CommandIssuer issuer) {
    +221        return issuer.isPlayer() ? "/" : "";
    +222    }
    +223}
     
     
     
    @@ -291,5 +292,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeConditionContext.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeConditionContext.html index 33a37f5f..e74e4313 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeConditionContext.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeConditionContext.html @@ -1,30 +1,31 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import net.md_5.bungee.api.CommandSender;
    -004import net.md_5.bungee.api.connection.ProxiedPlayer;
    -005
    -006public class BungeeConditionContext extends ConditionContext <BungeeCommandIssuer> {
    -007    BungeeConditionContext(BungeeCommandIssuer issuer, String config) {
    -008        super(issuer, config);
    -009    }
    -010
    -011
    -012    public CommandSender getSender() {
    -013        return getIssuer().getIssuer();
    -014    }
    -015
    -016    public ProxiedPlayer getPlayer() {
    -017        return getIssuer().getPlayer();
    -018    }
    -019}
    +
    001package co.aikar.commands;
    +002
    +003import net.md_5.bungee.api.CommandSender;
    +004import net.md_5.bungee.api.connection.ProxiedPlayer;
    +005
    +006public class BungeeConditionContext extends ConditionContext <BungeeCommandIssuer> {
    +007    BungeeConditionContext(BungeeCommandIssuer issuer, String config) {
    +008        super(issuer, config);
    +009    }
    +010
    +011
    +012    public CommandSender getSender() {
    +013        return getIssuer().getIssuer();
    +014    }
    +015
    +016    public ProxiedPlayer getPlayer() {
    +017        return getIssuer().getPlayer();
    +018    }
    +019}
     
     
     
    @@ -87,5 +88,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeLocales.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeLocales.html index 054d9b04..917be3af 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeLocales.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeLocales.html @@ -1,92 +1,93 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import co.aikar.locales.MessageKey;
    -004import net.md_5.bungee.config.Configuration;
    -005import net.md_5.bungee.config.ConfigurationProvider;
    -006import net.md_5.bungee.config.YamlConfiguration;
    -007
    -008import java.io.File;
    -009import java.io.IOException;
    -010import java.util.Locale;
    -011
    -012public class BungeeLocales extends Locales {
    -013    private final BungeeCommandManager manager;
    -014
    -015    public BungeeLocales(BungeeCommandManager manager) {
    -016        super(manager);
    -017
    -018        this.manager = manager;
    -019        this.addBundleClassLoader(this.manager.getPlugin().getClass().getClassLoader());
    -020    }
    -021
    -022    @Override
    -023    public void loadLanguages() {
    -024        super.loadLanguages();
    -025        String pluginName = "acf-" + manager.plugin.getDescription().getName();
    -026        addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
    -027    }
    -028
    -029    /**
    -030     * Loads the given file
    -031     *
    -032     * @param file
    -033     * @param locale
    -034     * @return If any language keys were added
    -035     * @throws IOException
    -036     */
    -037    public boolean loadYamlLanguageFile(File file, Locale locale) throws IOException {
    -038        Configuration yamlConfiguration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(file);
    -039        return loadLanguage(yamlConfiguration, locale);
    -040    }
    -041
    -042    /**
    -043     * Loads a file out of the plugins data folder by the given name
    -044     *
    -045     * @param file
    -046     * @param locale
    -047     * @return If any language keys were added
    -048     * @throws IOException
    -049     */
    -050    public boolean loadYamlLanguageFile(String file, Locale locale) throws IOException {
    -051        Configuration yamlConfiguration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(new File(this.manager.plugin.getDataFolder(), file));
    -052        return loadLanguage(yamlConfiguration, locale);
    -053    }
    -054
    -055
    -056    /**
    -057     * Loads every message from the Configuration object. Any nested values will be treated as namespace
    -058     * so acf-core:\n\tfoo: bar will be acf-core.foo = bar
    -059     *
    -060     * @param config
    -061     * @param locale
    -062     * @return If any language keys were added
    -063     */
    -064    public boolean loadLanguage(Configuration config, Locale locale) {
    -065        boolean loaded = false;
    -066        for (String parentKey : config.getKeys()) {
    -067            Configuration inner = config.getSection(parentKey);
    -068            if (inner == null) {
    -069                continue;
    -070            }
    -071            for (String key : inner.getKeys()) {
    -072                String value = inner.getString(key);
    -073                if (value != null && !value.isEmpty()) {
    -074                    addMessage(locale, MessageKey.of(parentKey + "." + key), value);
    -075                    loaded = true;
    -076                }
    -077            }
    -078        }
    -079        return loaded;
    -080    }
    -081}
    +
    001package co.aikar.commands;
    +002
    +003import co.aikar.locales.MessageKey;
    +004import net.md_5.bungee.config.Configuration;
    +005import net.md_5.bungee.config.ConfigurationProvider;
    +006import net.md_5.bungee.config.YamlConfiguration;
    +007
    +008import java.io.File;
    +009import java.io.IOException;
    +010import java.util.Locale;
    +011
    +012public class BungeeLocales extends Locales {
    +013    private final BungeeCommandManager manager;
    +014
    +015    public BungeeLocales(BungeeCommandManager manager) {
    +016        super(manager);
    +017
    +018        this.manager = manager;
    +019        this.addBundleClassLoader(this.manager.getPlugin().getClass().getClassLoader());
    +020    }
    +021
    +022    @Override
    +023    public void loadLanguages() {
    +024        super.loadLanguages();
    +025        String pluginName = "acf-" + manager.plugin.getDescription().getName();
    +026        addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase(Locale.ENGLISH));
    +027    }
    +028
    +029    /**
    +030     * Loads the given file
    +031     *
    +032     * @param file
    +033     * @param locale
    +034     * @return If any language keys were added
    +035     * @throws IOException
    +036     */
    +037    public boolean loadYamlLanguageFile(File file, Locale locale) throws IOException {
    +038        Configuration yamlConfiguration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(file);
    +039        return loadLanguage(yamlConfiguration, locale);
    +040    }
    +041
    +042    /**
    +043     * Loads a file out of the plugins data folder by the given name
    +044     *
    +045     * @param file
    +046     * @param locale
    +047     * @return If any language keys were added
    +048     * @throws IOException
    +049     */
    +050    public boolean loadYamlLanguageFile(String file, Locale locale) throws IOException {
    +051        Configuration yamlConfiguration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(new File(this.manager.plugin.getDataFolder(), file));
    +052        return loadLanguage(yamlConfiguration, locale);
    +053    }
    +054
    +055
    +056    /**
    +057     * Loads every message from the Configuration object. Any nested values will be treated as namespace
    +058     * so acf-core:\n\tfoo: bar will be acf-core.foo = bar
    +059     *
    +060     * @param config
    +061     * @param locale
    +062     * @return If any language keys were added
    +063     */
    +064    public boolean loadLanguage(Configuration config, Locale locale) {
    +065        boolean loaded = false;
    +066        for (String parentKey : config.getKeys()) {
    +067            Configuration inner = config.getSection(parentKey);
    +068            if (inner == null) {
    +069                continue;
    +070            }
    +071            for (String key : inner.getKeys()) {
    +072                String value = inner.getString(key);
    +073                if (value != null && !value.isEmpty()) {
    +074                    addMessage(locale, MessageKey.of(parentKey + "." + key), value);
    +075                    loaded = true;
    +076                }
    +077            }
    +078        }
    +079        return loaded;
    +080    }
    +081}
     
     
     
    @@ -149,5 +150,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeMessageFormatter.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeMessageFormatter.html index 6730a655..25e24c9f 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeMessageFormatter.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeMessageFormatter.html @@ -1,26 +1,27 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import net.md_5.bungee.api.ChatColor;
    -004
    -005public class BungeeMessageFormatter extends MessageFormatter<ChatColor> {
    -006
    -007    public BungeeMessageFormatter(ChatColor... colors) {
    -008        super(colors);
    -009    }
    -010
    -011    @Override
    -012    String format(ChatColor color, String message) {
    -013        return color + message;
    -014    }
    -015}
    +
    001package co.aikar.commands;
    +002
    +003import net.md_5.bungee.api.ChatColor;
    +004
    +005public class BungeeMessageFormatter extends MessageFormatter<ChatColor> {
    +006
    +007    public BungeeMessageFormatter(ChatColor... colors) {
    +008        super(colors);
    +009    }
    +010
    +011    @Override
    +012    String format(ChatColor color, String message) {
    +013        return color + message;
    +014    }
    +015}
     
     
     
    @@ -83,5 +84,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeRegisteredCommand.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeRegisteredCommand.html index fdff38fa..260ef177 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeRegisteredCommand.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeRegisteredCommand.html @@ -1,54 +1,55 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import java.lang.reflect.Method;
    -027
    -028public class BungeeRegisteredCommand extends RegisteredCommand<BungeeCommandExecutionContext> {
    -029
    -030    BungeeRegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) {
    -031        super(scope, command, method, prefSubCommand);
    -032    }
    -033
    -034    @Override
    -035    public void preCommand() {
    -036        super.preCommand();
    -037    }
    -038
    -039    @Override
    -040    public void postCommand() {
    -041        super.postCommand();
    -042    }
    -043}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import java.lang.reflect.Method;
    +027
    +028public class BungeeRegisteredCommand extends RegisteredCommand<BungeeCommandExecutionContext> {
    +029
    +030    BungeeRegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) {
    +031        super(scope, command, method, prefSubCommand);
    +032    }
    +033
    +034    @Override
    +035    public void preCommand() {
    +036        super.preCommand();
    +037    }
    +038
    +039    @Override
    +040    public void postCommand() {
    +041        super.postCommand();
    +042    }
    +043}
     
     
     
    @@ -111,5 +112,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/BungeeRootCommand.html b/docs/acf-bungee/src-html/co/aikar/commands/BungeeRootCommand.html index 40617528..c18a8791 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/BungeeRootCommand.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/BungeeRootCommand.html @@ -1,111 +1,112 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import com.google.common.collect.HashMultimap;
    -027import com.google.common.collect.SetMultimap;
    -028import net.md_5.bungee.api.CommandSender;
    -029import net.md_5.bungee.api.plugin.Command;
    -030import net.md_5.bungee.api.plugin.TabExecutor;
    -031
    -032import java.util.ArrayList;
    -033import java.util.List;
    -034
    -035public class BungeeRootCommand extends Command implements RootCommand, TabExecutor {
    -036
    -037    private final BungeeCommandManager manager;
    -038    private final String name;
    -039    private BaseCommand defCommand;
    -040    private SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
    -041    private List<BaseCommand> children = new ArrayList<>();
    -042    boolean isRegistered = false;
    -043    private String uniquePermission;
    -044
    -045    BungeeRootCommand(BungeeCommandManager manager, String name) {
    -046        super(name);
    -047        this.manager = manager;
    -048        this.name = name;
    -049    }
    -050
    -051    @Override
    -052    public String getCommandName() {
    -053        return name;
    -054    }
    -055
    -056    @Override
    -057    public void addChild(BaseCommand command) {
    -058        if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) {
    -059            this.defCommand = command;
    -060
    -061        }
    -062        this.addChildShared(this.children, this.subCommands, command);
    -063        this.uniquePermission = getUniquePermission();
    -064    }
    -065
    -066    @Override
    -067    public CommandManager getManager() {
    -068        return manager;
    -069    }
    -070
    -071    @Override
    -072    public SetMultimap<String, RegisteredCommand> getSubCommands() {
    -073        return subCommands;
    -074    }
    -075
    -076    @Override
    -077    public List<BaseCommand> getChildren() {
    -078        return children;
    -079    }
    -080
    -081    @Override
    -082    public void execute(CommandSender sender, String[] args) {
    -083        execute(manager.getCommandIssuer(sender), getName(), args);
    -084    }
    -085
    -086    @Override
    -087    public String getPermission() {
    -088        return uniquePermission;
    -089    }
    -090
    -091    @Override
    -092    public Iterable<String> onTabComplete(CommandSender commandSender, String[] strings) {
    -093        return getTabCompletions(manager.getCommandIssuer(commandSender), getName(), strings);
    -094    }
    -095
    -096    @Override
    -097    public BaseCommand getDefCommand() {
    -098        return defCommand;
    -099    }
    -100}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import com.google.common.collect.HashMultimap;
    +027import com.google.common.collect.SetMultimap;
    +028import net.md_5.bungee.api.CommandSender;
    +029import net.md_5.bungee.api.plugin.Command;
    +030import net.md_5.bungee.api.plugin.TabExecutor;
    +031
    +032import java.util.ArrayList;
    +033import java.util.List;
    +034
    +035public class BungeeRootCommand extends Command implements RootCommand, TabExecutor {
    +036
    +037    private final BungeeCommandManager manager;
    +038    private final String name;
    +039    private BaseCommand defCommand;
    +040    private SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
    +041    private List<BaseCommand> children = new ArrayList<>();
    +042    boolean isRegistered = false;
    +043    private String uniquePermission;
    +044
    +045    BungeeRootCommand(BungeeCommandManager manager, String name) {
    +046        super(name);
    +047        this.manager = manager;
    +048        this.name = name;
    +049    }
    +050
    +051    @Override
    +052    public String getCommandName() {
    +053        return name;
    +054    }
    +055
    +056    @Override
    +057    public void addChild(BaseCommand command) {
    +058        if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) {
    +059            this.defCommand = command;
    +060
    +061        }
    +062        this.addChildShared(this.children, this.subCommands, command);
    +063        this.uniquePermission = getUniquePermission();
    +064    }
    +065
    +066    @Override
    +067    public CommandManager getManager() {
    +068        return manager;
    +069    }
    +070
    +071    @Override
    +072    public SetMultimap<String, RegisteredCommand> getSubCommands() {
    +073        return subCommands;
    +074    }
    +075
    +076    @Override
    +077    public List<BaseCommand> getChildren() {
    +078        return children;
    +079    }
    +080
    +081    @Override
    +082    public void execute(CommandSender sender, String[] args) {
    +083        execute(manager.getCommandIssuer(sender), getName(), args);
    +084    }
    +085
    +086    @Override
    +087    public String getPermission() {
    +088        return uniquePermission;
    +089    }
    +090
    +091    @Override
    +092    public Iterable<String> onTabComplete(CommandSender commandSender, String[] strings) {
    +093        return getTabCompletions(manager.getCommandIssuer(commandSender), getName(), strings);
    +094    }
    +095
    +096    @Override
    +097    public BaseCommand getDefCommand() {
    +098        return defCommand;
    +099    }
    +100}
     
     
     
    @@ -168,5 +169,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/MinecraftMessageKeys.html b/docs/acf-bungee/src-html/co/aikar/commands/MinecraftMessageKeys.html index 7b2b5484..46ee613b 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/MinecraftMessageKeys.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/MinecraftMessageKeys.html @@ -1,29 +1,32 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import co.aikar.locales.MessageKey;
    -004import co.aikar.locales.MessageKeyProvider;
    -005
    -006public enum MinecraftMessageKeys implements MessageKeyProvider {
    -007    USERNAME_TOO_SHORT,
    -008    IS_NOT_A_VALID_NAME,
    -009    MULTIPLE_PLAYERS_MATCH,
    -010    NO_PLAYER_FOUND_SERVER,
    -011    NO_PLAYER_FOUND
    -012    ;
    -013
    -014    private final MessageKey key = MessageKey.of("acf-minecraft." + this.name().toLowerCase());
    -015    public MessageKey getMessageKey() {
    -016        return key;
    -017    }
    -018}
    +
    001package co.aikar.commands;
    +002
    +003import co.aikar.locales.MessageKey;
    +004import co.aikar.locales.MessageKeyProvider;
    +005
    +006import java.util.Locale;
    +007
    +008public enum MinecraftMessageKeys implements MessageKeyProvider {
    +009    USERNAME_TOO_SHORT,
    +010    IS_NOT_A_VALID_NAME,
    +011    MULTIPLE_PLAYERS_MATCH,
    +012    NO_PLAYER_FOUND_SERVER,
    +013    NO_PLAYER_FOUND
    +014    ;
    +015
    +016    private final MessageKey key = MessageKey.of("acf-minecraft." + this.name().toLowerCase(Locale.ENGLISH));
    +017    public MessageKey getMessageKey() {
    +018        return key;
    +019    }
    +020}
     
     
     
    @@ -86,5 +89,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/bungee/contexts/OnlinePlayer.html b/docs/acf-bungee/src-html/co/aikar/commands/bungee/contexts/OnlinePlayer.html index 5808d113..636b7aad 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/bungee/contexts/OnlinePlayer.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/bungee/contexts/OnlinePlayer.html @@ -1,70 +1,71 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands.bungee.contexts;
    -025
    -026import net.md_5.bungee.api.connection.ProxiedPlayer;
    -027
    -028import java.util.Objects;
    -029
    -030public class OnlinePlayer {
    -031
    -032    public final ProxiedPlayer player;
    -033
    -034    public OnlinePlayer(ProxiedPlayer player) {
    -035        this.player = player;
    -036    }
    -037
    -038    public ProxiedPlayer getPlayer() {
    -039        return player;
    -040    }
    -041
    -042    @Override
    -043    public boolean equals(Object o) {
    -044        if (this == o) return true;
    -045        if (o == null || getClass() != o.getClass()) return false;
    -046        OnlinePlayer that = (OnlinePlayer) o;
    -047        return Objects.equals(player, that.player);
    -048    }
    -049
    -050    @Override
    -051    public int hashCode() {
    -052        return Objects.hash(player);
    -053    }
    -054
    -055    @Override
    -056    public String toString() {
    -057        return "OnlinePlayer{player=" + player + '}';
    -058    }
    -059}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands.bungee.contexts;
    +025
    +026import net.md_5.bungee.api.connection.ProxiedPlayer;
    +027
    +028import java.util.Objects;
    +029
    +030public class OnlinePlayer {
    +031
    +032    public final ProxiedPlayer player;
    +033
    +034    public OnlinePlayer(ProxiedPlayer player) {
    +035        this.player = player;
    +036    }
    +037
    +038    public ProxiedPlayer getPlayer() {
    +039        return player;
    +040    }
    +041
    +042    @Override
    +043    public boolean equals(Object o) {
    +044        if (this == o) return true;
    +045        if (o == null || getClass() != o.getClass()) return false;
    +046        OnlinePlayer that = (OnlinePlayer) o;
    +047        return Objects.equals(player, that.player);
    +048    }
    +049
    +050    @Override
    +051    public int hashCode() {
    +052        return Objects.hash(player);
    +053    }
    +054
    +055    @Override
    +056    public String toString() {
    +057        return "OnlinePlayer{player=" + player + '}';
    +058    }
    +059}
     
     
     
    @@ -127,5 +128,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/src-html/co/aikar/commands/contexts/OnlineProxiedPlayer.html b/docs/acf-bungee/src-html/co/aikar/commands/contexts/OnlineProxiedPlayer.html index eca0c2b5..f265aced 100644 --- a/docs/acf-bungee/src-html/co/aikar/commands/contexts/OnlineProxiedPlayer.html +++ b/docs/acf-bungee/src-html/co/aikar/commands/contexts/OnlineProxiedPlayer.html @@ -1,25 +1,26 @@ - + Source code +
    -
    001package co.aikar.commands.contexts;
    -002
    -003import co.aikar.commands.bungee.contexts.OnlinePlayer;
    -004import net.md_5.bungee.api.connection.ProxiedPlayer;
    -005
    -006/**
    -007 * @deprecated Use {@link OnlinePlayer}
    -008 */
    -009@Deprecated
    -010public class OnlineProxiedPlayer extends OnlinePlayer {
    -011    public OnlineProxiedPlayer(ProxiedPlayer player) {
    -012        super(player);
    -013    }
    -014}
    +
    001package co.aikar.commands.contexts;
    +002
    +003import co.aikar.commands.bungee.contexts.OnlinePlayer;
    +004import net.md_5.bungee.api.connection.ProxiedPlayer;
    +005
    +006/**
    +007 * @deprecated Use {@link OnlinePlayer}
    +008 */
    +009@Deprecated
    +010public class OnlineProxiedPlayer extends OnlinePlayer {
    +011    public OnlineProxiedPlayer(ProxiedPlayer player) {
    +012        super(player);
    +013    }
    +014}
     
     
     
    @@ -82,5 +83,6 @@
     
     
    +
    diff --git a/docs/acf-bungee/stylesheet.css b/docs/acf-bungee/stylesheet.css index 98055b22..fa246765 100644 --- a/docs/acf-bungee/stylesheet.css +++ b/docs/acf-bungee/stylesheet.css @@ -1,35 +1,51 @@ -/* Javadoc style sheet */ -/* -Overall document style -*/ +/* + * Javadoc style sheet + */ @import url('resources/fonts/dejavu.css'); +/* + * Styles for individual HTML elements. + * + * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular + * HTML element throughout the page. + */ + body { background-color:#ffffff; color:#353833; font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; font-size:14px; margin:0; + padding:0; + height:100%; + width:100%; +} +iframe { + margin:0; + padding:0; + height:100%; + width:100%; + overflow-y:scroll; + border:none; } a:link, a:visited { text-decoration:none; color:#4A6782; } -a:hover, a:focus { +a[href]:hover, a[href]:focus { text-decoration:none; color:#bb7a2a; } -a:active { - text-decoration:none; - color:#4A6782; -} a[name] { color:#353833; } -a[name]:hover { - text-decoration:none; - color:#353833; +a[name]:before, a[name]:target, a[id]:before, a[id]:target { + content:""; + display:inline-block; + position:relative; + padding-top:129px; + margin-top:-129px; } pre { font-family:'DejaVu Sans Mono', monospace; @@ -78,9 +94,16 @@ table tr td dt code { sup { font-size:8px; } + /* -Document title and Copyright styles -*/ + * Styles for HTML generated by javadoc. + * + * These are style classes that are used by the standard doclet to generate HTML documentation. + */ + +/* + * Styles for document title and copyright. + */ .clear { clear:both; height:0px; @@ -111,8 +134,8 @@ Document title and Copyright styles font-weight:bold; } /* -Navigation bar styles -*/ + * Styles for navigation bar. + */ .bar { background-color:#4D7A97; color:#FFFFFF; @@ -121,6 +144,15 @@ Navigation bar styles font-size:11px; margin:0; } +.navPadding { + padding-top: 107px; +} +.fixedNav { + position:fixed; + width:100%; + z-index:999; + background-color:#ffffff; +} .topNav { background-color:#4D7A97; color:#FFFFFF; @@ -170,7 +202,22 @@ ul.navList li{ padding: 5px 6px; text-transform:uppercase; } -ul.subNavList li{ +ul.navListSearch { + float:right; + margin:0 0 0 0; + padding:0; +} +ul.navListSearch li { + list-style:none; + float:right; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch li label { + position:relative; + right:-16px; +} +ul.subNavList li { list-style:none; float:left; } @@ -196,21 +243,29 @@ ul.subNavList li{ overflow:hidden; } /* -Page header and footer styles -*/ + * Styles for page header and footer. + */ .header, .footer { clear:both; margin:0 20px; padding:5px 0 0 0; } -.indexHeader { - margin:10px; +.indexNav { position:relative; + font-size:12px; + background-color:#dee3e9; } -.indexHeader span{ - margin-right:15px; +.indexNav ul { + margin-top:0; + padding:5px; } -.indexHeader h1 { +.indexNav ul li { + display:inline; + list-style-type:none; + padding-right:10px; + text-transform:uppercase; +} +.indexNav h1 { font-size:13px; } .title { @@ -232,8 +287,8 @@ Page header and footer styles font-size:13px; } /* -Heading styles -*/ + * Styles for headings. + */ div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { background-color:#dee3e9; border:1px solid #d0d9e0; @@ -254,9 +309,10 @@ ul.blockList li.blockList h2 { padding:0px 0 20px 0; } /* -Page layout container styles -*/ -.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + * Styles for page layout containers. + */ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer, +.allClassesContainer, .allPackagesContainer { clear:both; padding:10px 20px; position:relative; @@ -287,7 +343,7 @@ Page layout container styles .contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { margin:5px 0 10px 0px; font-size:14px; - font-family:'DejaVu Sans Mono',monospace; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } .serializedFormContainer dl.nameValue dt { margin-left:1px; @@ -301,8 +357,11 @@ Page layout container styles display:inline; } /* -List styles -*/ + * Styles for lists. + */ +li.circle { + list-style:circle; +} ul.horizontal li { display:inline; font-size:0.9em; @@ -355,19 +414,22 @@ table tr td dl, table tr td dl dt, table tr td dl dd { margin-bottom:1px; } /* -Table styles -*/ -.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + * Styles for tables. + */ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary, +.requiresSummary, .packagesSummary, .providesSummary, .usesSummary { width:100%; + border-spacing:0; border-left:1px solid #EEE; border-right:1px solid #EEE; border-bottom:1px solid #EEE; } -.overviewSummary, .memberSummary { +.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary { padding:0px; } .overviewSummary caption, .memberSummary caption, .typeSummary caption, -.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption, +.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption { position:relative; text-align:left; background-repeat:no-repeat; @@ -382,17 +444,31 @@ Table styles white-space:pre; } .overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, -.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.constantsSummary caption a:link, .deprecatedSummary caption a:link, +.requiresSummary caption a:link, .packagesSummary caption a:link, .providesSummary caption a:link, +.usesSummary caption a:link, .overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, -.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.requiresSummary caption a:hover, .packagesSummary caption a:hover, .providesSummary caption a:hover, +.usesSummary caption a:hover, .overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, -.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.constantsSummary caption a:active, .deprecatedSummary caption a:active, +.requiresSummary caption a:active, .packagesSummary caption a:active, .providesSummary caption a:active, +.usesSummary caption a:active, .overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, -.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { +.constantsSummary caption a:visited, .deprecatedSummary caption a:visited, +.requiresSummary caption a:visited, .packagesSummary caption a:visited, .providesSummary caption a:visited, +.usesSummary caption a:visited { color:#FFFFFF; } +.useSummary caption a:link, .useSummary caption a:hover, .useSummary caption a:active, +.useSummary caption a:visited { + color:#1f389c; +} .overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, -.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span, +.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span, +.usesSummary caption span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -404,7 +480,8 @@ Table styles border: none; height:16px; } -.memberSummary caption span.activeTableTab span { +.memberSummary caption span.activeTableTab span, .packagesSummary caption span.activeTableTab span, +.overviewSummary caption span.activeTableTab span, .typeSummary caption span.activeTableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -415,7 +492,8 @@ Table styles background-color:#F8981D; height:16px; } -.memberSummary caption span.tableTab span { +.memberSummary caption span.tableTab span, .packagesSummary caption span.tableTab span, +.overviewSummary caption span.tableTab span, .typeSummary caption span.tableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -426,7 +504,10 @@ Table styles background-color:#4D7A97; height:16px; } -.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab, +.packagesSummary caption span.tableTab, .packagesSummary caption span.activeTableTab, +.overviewSummary caption span.tableTab, .overviewSummary caption span.activeTableTab, +.typeSummary caption span.tableTab, .typeSummary caption span.activeTableTab { padding-top:0px; padding-left:0px; padding-right:0px; @@ -435,14 +516,16 @@ Table styles display:inline; } .overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, -.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd, +.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd { display:none; width:5px; position:relative; float:left; background-color:#F8981D; } -.memberSummary .activeTableTab .tabEnd { +.memberSummary .activeTableTab .tabEnd, .packagesSummary .activeTableTab .tabEnd, +.overviewSummary .activeTableTab .tabEnd, .typeSummary .activeTableTab .tabEnd { display:none; width:5px; margin-right:3px; @@ -450,66 +533,88 @@ Table styles float:left; background-color:#F8981D; } -.memberSummary .tableTab .tabEnd { +.memberSummary .tableTab .tabEnd, .packagesSummary .tableTab .tabEnd, +.overviewSummary .tableTab .tabEnd, .typeSummary .tableTab .tabEnd { display:none; width:5px; margin-right:3px; position:relative; background-color:#4D7A97; float:left; - +} +.rowColor th, .altColor th { + font-weight:normal; } .overviewSummary td, .memberSummary td, .typeSummary td, -.useSummary td, .constantsSummary td, .deprecatedSummary td { +.useSummary td, .constantsSummary td, .deprecatedSummary td, +.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td { text-align:left; padding:0px 0px 12px 10px; } -th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, -td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .useSummary th, +.constantsSummary th, .packagesSummary th, td.colFirst, td.colSecond, td.colLast, .useSummary td, +.constantsSummary td { vertical-align:top; padding-right:0px; padding-top:8px; padding-bottom:3px; } -th.colFirst, th.colLast, th.colOne, .constantsSummary th { +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .constantsSummary th, +.packagesSummary th { background:#dee3e9; text-align:left; padding:8px 3px 3px 7px; } td.colFirst, th.colFirst { - white-space:nowrap; font-size:13px; } -td.colLast, th.colLast { +td.colSecond, th.colSecond, td.colLast, th.colConstructorName, th.colDeprecatedItemName, th.colLast { font-size:13px; } -td.colOne, th.colOne { +.constantsSummary th, .packagesSummary th { + font-size:13px; +} +.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst, +.providesSummary td.colLast { + white-space:normal; font-size:13px; } .overviewSummary td.colFirst, .overviewSummary th.colFirst, -.useSummary td.colFirst, .useSummary th.colFirst, -.overviewSummary td.colOne, .overviewSummary th.colOne, +.requiresSummary td.colFirst, .requiresSummary th.colFirst, +.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th, +.usesSummary td.colFirst, .usesSummary th.colFirst, +.providesSummary td.colFirst, .providesSummary th.colFirst, .memberSummary td.colFirst, .memberSummary th.colFirst, -.memberSummary td.colOne, .memberSummary th.colOne, -.typeSummary td.colFirst{ - width:25%; +.memberSummary td.colSecond, .memberSummary th.colSecond, .memberSummary th.colConstructorName, +.typeSummary td.colFirst, .typeSummary th.colFirst { vertical-align:top; } -td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { +.packagesSummary th.colLast, .packagesSummary td.colLast { + white-space:normal; +} +td.colFirst a:link, td.colFirst a:visited, +td.colSecond a:link, td.colSecond a:visited, +th.colFirst a:link, th.colFirst a:visited, +th.colSecond a:link, th.colSecond a:visited, +th.colConstructorName a:link, th.colConstructorName a:visited, +th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited, +.constantValuesContainer td a:link, .constantValuesContainer td a:visited, +.allClassesContainer td a:link, .allClassesContainer td a:visited, +.allPackagesContainer td a:link, .allPackagesContainer td a:visited { font-weight:bold; } .tableSubHeadingColor { background-color:#EEEEFF; } -.altColor { +.altColor, .altColor th { background-color:#FFFFFF; } -.rowColor { +.rowColor, .rowColor th { background-color:#EEEEEF; } /* -Content styles -*/ + * Styles for contents. + */ .description pre { margin-top:0; } @@ -520,27 +625,22 @@ Content styles .docSummary { padding:0; } - ul.blockList ul.blockList ul.blockList li.blockList h3 { font-style:normal; } - div.block { font-size:14px; font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } - td.colLast div { padding-top:0px; } - - td.colLast a { padding-bottom:3px; } /* -Formatting effect styles -*/ + * Styles for formatting effect. + */ .sourceLineNo { color:green; padding:0 30px 0 0; @@ -555,20 +655,252 @@ h1.hidden { margin:3px 10px 2px 0px; color:#474747; } -.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { +.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink, +.moduleLabelInPackage, .moduleLabelInType, .overrideSpecifyLabel, .packageLabelInType, +.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, +.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { font-weight:bold; } .deprecationComment, .emphasizedPhrase, .interfaceName { font-style:italic; } - -div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +.deprecationBlock { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +div.block div.deprecationComment, div.block div.block span.emphasizedPhrase, div.block div.block span.interfaceName { font-style:normal; } - -div.contentContainer ul.blockList li.blockList h2{ +div.contentContainer ul.blockList li.blockList h2 { padding-bottom:0px; } +/* + * Styles for IFRAME. + */ +.mainContainer { + margin:0 auto; + padding:0; + height:100%; + width:100%; + position:fixed; + top:0; + left:0; +} +.leftContainer { + height:100%; + position:fixed; + width:320px; +} +.leftTop { + position:relative; + float:left; + width:315px; + top:0; + left:0; + height:30%; + border-right:6px solid #ccc; + border-bottom:6px solid #ccc; +} +.leftBottom { + position:relative; + float:left; + width:315px; + bottom:0; + left:0; + height:70%; + border-right:6px solid #ccc; + border-top:1px solid #000; +} +.rightContainer { + position:absolute; + left:320px; + top:0; + bottom:0; + height:100%; + right:0; + border-left:1px solid #000; +} +.rightIframe { + margin:0; + padding:0; + height:100%; + right:30px; + width:100%; + overflow:visible; + margin-bottom:30px; +} +/* + * Styles specific to HTML5 elements. + */ +main, nav, header, footer, section { + display:block; +} +/* + * Styles for javadoc search. + */ +.ui-autocomplete-category { + font-weight:bold; + font-size:15px; + padding:7px 0 7px 3px; + background-color:#4D7A97; + color:#FFFFFF; +} +.resultItem { + font-size:13px; +} +.ui-autocomplete { + max-height:85%; + max-width:65%; + overflow-y:scroll; + overflow-x:scroll; + white-space:nowrap; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); +} +ul.ui-autocomplete { + position:fixed; + z-index:999999; +} +ul.ui-autocomplete li { + float:left; + clear:both; + width:100%; +} +.resultHighlight { + font-weight:bold; +} +#search { + background-image:url('resources/glass.png'); + background-size:13px; + background-repeat:no-repeat; + background-position:2px 3px; + padding-left:20px; + position:relative; + right:-18px; +} +#reset { + background-color: rgb(255,255,255); + background-image:url('resources/x.png'); + background-position:center; + background-repeat:no-repeat; + background-size:12px; + border:0 none; + width:16px; + height:17px; + position:relative; + left:-4px; + top:-4px; + font-size:0px; +} +.watermark { + color:#545454; +} +.searchTagDescResult { + font-style:italic; + font-size:11px; +} +.searchTagHolderResult { + font-style:italic; + font-size:12px; +} +.searchTagResult:before, .searchTagResult:target { + color:red; +} +.moduleGraph span { + display:none; + position:absolute; +} +.moduleGraph:hover span { + display:block; + margin: -100px 0 0 100px; + z-index: 1; +} +.methodSignature { + white-space:normal; +} + +/* + * Styles for user-provided tables. + * + * borderless: + * No borders, vertical margins, styled caption. + * This style is provided for use with existing doc comments. + * In general, borderless tables should not be used for layout purposes. + * + * plain: + * Plain borders around table and cells, vertical margins, styled caption. + * Best for small tables or for complex tables for tables with cells that span + * rows and columns, when the "striped" style does not work well. + * + * striped: + * Borders around the table and vertical borders between cells, striped rows, + * vertical margins, styled caption. + * Best for tables that have a header row, and a body containing a series of simple rows. + */ + +table.borderless, +table.plain, +table.striped { + margin-top: 10px; + margin-bottom: 10px; +} +table.borderless > caption, +table.plain > caption, +table.striped > caption { + font-weight: bold; + font-size: smaller; +} +table.borderless th, table.borderless td, +table.plain th, table.plain td, +table.striped th, table.striped td { + padding: 2px 5px; +} +table.borderless, +table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, +table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { + border: none; +} +table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { + background-color: transparent; +} +table.plain { + border-collapse: collapse; + border: 1px solid black; +} +table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { + background-color: transparent; +} +table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, +table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { + border: 1px solid black; +} +table.striped { + border-collapse: collapse; + border: 1px solid black; +} +table.striped > thead { + background-color: #E3E3E3; +} +table.striped > thead > tr > th, table.striped > thead > tr > td { + border: 1px solid black; +} +table.striped > tbody > tr:nth-child(even) { + background-color: #EEE +} +table.striped > tbody > tr:nth-child(odd) { + background-color: #FFF +} +table.striped > tbody > tr > th, table.striped > tbody > tr > td { + border-left: 1px solid black; + border-right: 1px solid black; +} +table.striped > tbody > tr > th { + font-weight: normal; +} diff --git a/docs/acf-bungee/type-search-index.js b/docs/acf-bungee/type-search-index.js new file mode 100644 index 00000000..335abd0b --- /dev/null +++ b/docs/acf-bungee/type-search-index.js @@ -0,0 +1 @@ +typeSearchIndex = [{"p":"co.aikar.commands","l":"ACFBungeeListener"},{"p":"co.aikar.commands","l":"ACFBungeeUtil"},{"l":"All Classes","url":"allclasses-index.html"},{"p":"co.aikar.commands","l":"BungeeCommandCompletionContext"},{"p":"co.aikar.commands","l":"BungeeCommandCompletions"},{"p":"co.aikar.commands","l":"BungeeCommandContexts"},{"p":"co.aikar.commands","l":"BungeeCommandExecutionContext"},{"p":"co.aikar.commands","l":"BungeeCommandIssuer"},{"p":"co.aikar.commands","l":"BungeeCommandManager"},{"p":"co.aikar.commands","l":"BungeeConditionContext"},{"p":"co.aikar.commands","l":"BungeeLocales"},{"p":"co.aikar.commands","l":"BungeeMessageFormatter"},{"p":"co.aikar.commands","l":"BungeeRegisteredCommand"},{"p":"co.aikar.commands","l":"BungeeRootCommand"},{"p":"co.aikar.commands","l":"MinecraftMessageKeys"},{"p":"co.aikar.commands.bungee.contexts","l":"OnlinePlayer"},{"p":"co.aikar.commands.contexts","l":"OnlineProxiedPlayer"}] \ No newline at end of file diff --git a/docs/acf-bungee/type-search-index.zip b/docs/acf-bungee/type-search-index.zip new file mode 100644 index 00000000..8229f2c8 Binary files /dev/null and b/docs/acf-bungee/type-search-index.zip differ diff --git a/docs/acf-core/allclasses-index.html b/docs/acf-core/allclasses-index.html new file mode 100644 index 00000000..f2e3c0a8 --- /dev/null +++ b/docs/acf-core/allclasses-index.html @@ -0,0 +1,510 @@ + + + + + +All Classes (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    All Classes

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + + diff --git a/docs/acf-core/allclasses.html b/docs/acf-core/allclasses.html new file mode 100644 index 00000000..b507768a --- /dev/null +++ b/docs/acf-core/allclasses.html @@ -0,0 +1,94 @@ + + + + + +All Classes (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + +

    All Classes

    +
    + +
    + + diff --git a/docs/acf-core/allpackages-index.html b/docs/acf-core/allpackages-index.html new file mode 100644 index 00000000..62eaef54 --- /dev/null +++ b/docs/acf-core/allpackages-index.html @@ -0,0 +1,181 @@ + + + + + +All Packages (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    All Packages

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + + diff --git a/docs/acf-core/co/aikar/commands/ACFUtil.html b/docs/acf-core/co/aikar/commands/ACFUtil.html index ce14f15e..dc9fa76e 100644 --- a/docs/acf-core/co/aikar/commands/ACFUtil.html +++ b/docs/acf-core/co/aikar/commands/ACFUtil.html @@ -1,12 +1,21 @@ - + - ACFUtil (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class ACFUtil

    @@ -117,391 +140,467 @@ extends
  • +
      -
    • +
    • Field Summary

      - +
      - + + - - + + +
      Fields 
      Modifier and TypeField and DescriptionFieldDescription
      static RandomRANDOM static RandomRANDOM 
    +
    +
    +
  • @@ -509,315 +608,318 @@ extends
  • +
    +
    +
  • + + diff --git a/docs/acf-core/co/aikar/commands/AnnotationProcessor.html b/docs/acf-core/co/aikar/commands/AnnotationProcessor.html index d012fc33..7887c1ce 100644 --- a/docs/acf-core/co/aikar/commands/AnnotationProcessor.html +++ b/docs/acf-core/co/aikar/commands/AnnotationProcessor.html @@ -1,12 +1,21 @@ - + - AnnotationProcessor (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Interface AnnotationProcessor<T extends Annotation>

    + +

    Interface AnnotationProcessor<T extends Annotation>

    @@ -100,13 +124,12 @@ var activeTableTab = "activeTableTab";
  • All Known Implementing Classes:
    -
    ConditionsProcessor
    +
    ConditionsProcessor

    -
    Deprecated.
    -
    -
    @Deprecated
    -public interface AnnotationProcessor<T extends Annotation>
    +
    @Deprecated
    +public interface AnnotationProcessor<T extends Annotation>
    +
    Deprecated.
  • @@ -114,74 +137,85 @@ public interface
  • +
    +
  • @@ -189,121 +223,126 @@ public interface
  • +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/BaseCommand.html b/docs/acf-core/co/aikar/commands/BaseCommand.html index b22b81b8..dc642f7b 100644 --- a/docs/acf-core/co/aikar/commands/BaseCommand.html +++ b/docs/acf-core/co/aikar/commands/BaseCommand.html @@ -1,12 +1,21 @@ - + - BaseCommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class BaseCommand

    @@ -329,30 +387,33 @@ extends
  • +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandCompletionContext.html b/docs/acf-core/co/aikar/commands/CommandCompletionContext.html index 56cf5201..1713cc68 100644 --- a/docs/acf-core/co/aikar/commands/CommandCompletionContext.html +++ b/docs/acf-core/co/aikar/commands/CommandCompletionContext.html @@ -1,12 +1,21 @@ - + - CommandCompletionContext (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Class CommandCompletionContext<I extends CommandIssuer>

    + +

    Class CommandCompletionContext<I extends CommandIssuer>

    @@ -117,88 +140,105 @@ extends
  • +
      -
    • +
    • Field Summary

      - +
      - + + - - + + +
      Fields 
      Modifier and TypeField and DescriptionFieldDescription
      protected Iissuer protected Iissuer 
    +
    +
    +
  • @@ -206,147 +246,154 @@ extends
  • +
    +
    +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandCompletions.AsyncCommandCompletionHandler.html b/docs/acf-core/co/aikar/commands/CommandCompletions.AsyncCommandCompletionHandler.html index 3d157975..024605c4 100644 --- a/docs/acf-core/co/aikar/commands/CommandCompletions.AsyncCommandCompletionHandler.html +++ b/docs/acf-core/co/aikar/commands/CommandCompletions.AsyncCommandCompletionHandler.html @@ -1,12 +1,21 @@ - + - CommandCompletions.AsyncCommandCompletionHandler (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Interface CommandCompletions.AsyncCommandCompletionHandler<C extends CommandCompletionContext>

    + +

    Interface CommandCompletions.AsyncCommandCompletionHandler<C extends CommandCompletionContext>

    @@ -111,35 +134,40 @@ extends
  • +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandCompletions.CommandCompletionHandler.html b/docs/acf-core/co/aikar/commands/CommandCompletions.CommandCompletionHandler.html index c843d26f..8dc5b8f9 100644 --- a/docs/acf-core/co/aikar/commands/CommandCompletions.CommandCompletionHandler.html +++ b/docs/acf-core/co/aikar/commands/CommandCompletions.CommandCompletionHandler.html @@ -1,12 +1,21 @@ - + - CommandCompletions.CommandCompletionHandler (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Interface CommandCompletions.CommandCompletionHandler<C extends CommandCompletionContext>

    + +

    Interface CommandCompletions.CommandCompletionHandler<C extends CommandCompletionContext>

    @@ -100,15 +124,14 @@ var activeTableTab = "activeTableTab";
  • All Known Subinterfaces:
    -
    CommandCompletions.AsyncCommandCompletionHandler<C>
    +
    CommandCompletions.AsyncCommandCompletionHandler<C>
    Enclosing class:
    -
    CommandCompletions<C extends CommandCompletionContext>
    +
    CommandCompletions<C extends CommandCompletionContext>

    -
    -
    public static interface CommandCompletions.CommandCompletionHandler<C extends CommandCompletionContext>
    +
    public static interface CommandCompletions.CommandCompletionHandler<C extends CommandCompletionContext>
  • @@ -116,24 +139,28 @@ var activeTableTab = "activeTableTab";
    @@ -141,44 +168,49 @@ var activeTableTab = "activeTableTab"; +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandCompletions.SyncCompletionRequired.html b/docs/acf-core/co/aikar/commands/CommandCompletions.SyncCompletionRequired.html index 4ea81063..cd8c2f38 100644 --- a/docs/acf-core/co/aikar/commands/CommandCompletions.SyncCompletionRequired.html +++ b/docs/acf-core/co/aikar/commands/CommandCompletions.SyncCompletionRequired.html @@ -1,12 +1,21 @@ - + - CommandCompletions.SyncCompletionRequired (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class CommandCompletions.SyncCompletionRequired

    @@ -183,37 +212,42 @@ extends
  • +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandCompletions.html b/docs/acf-core/co/aikar/commands/CommandCompletions.html index 9bf7291d..8c40ac2d 100644 --- a/docs/acf-core/co/aikar/commands/CommandCompletions.html +++ b/docs/acf-core/co/aikar/commands/CommandCompletions.html @@ -1,12 +1,21 @@ - + - CommandCompletions (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Class CommandCompletions<C extends CommandCompletionContext>

    + +

    Class CommandCompletions<C extends CommandCompletionContext>

    @@ -117,120 +140,140 @@ extends
  • +
    +
    +
    +
    +
    +
  • @@ -238,36 +281,39 @@ extends
  • +
    +
    +
  • + diff --git a/docs/acf-core/co/aikar/commands/CommandConditions.ParameterCondition.html b/docs/acf-core/co/aikar/commands/CommandConditions.ParameterCondition.html index 41e18679..cc8adf9b 100644 --- a/docs/acf-core/co/aikar/commands/CommandConditions.ParameterCondition.html +++ b/docs/acf-core/co/aikar/commands/CommandConditions.ParameterCondition.html @@ -1,12 +1,21 @@ - + - CommandConditions.ParameterCondition (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Interface CommandConditions.ParameterCondition<P,CEC extends CommandExecutionContext,I extends CommandIssuer>

    + +

    Interface CommandConditions.ParameterCondition<P,​CEC extends CommandExecutionContext,​I extends CommandIssuer>

    @@ -100,11 +124,10 @@ var activeTableTab = "activeTableTab";
  • Enclosing class:
    -
    CommandConditions<I extends CommandIssuer,CEC extends CommandExecutionContext<CEC,I>,CC extends ConditionContext<I>>
    +
    CommandConditions<I extends CommandIssuer,​CEC extends CommandExecutionContext<CEC,​I>,​CC extends ConditionContext<I>>

    -
    -
    public static interface CommandConditions.ParameterCondition<P,CEC extends CommandExecutionContext,I extends CommandIssuer>
    +
    public static interface CommandConditions.ParameterCondition<P,​CEC extends CommandExecutionContext,​I extends CommandIssuer>
  • @@ -112,26 +135,30 @@ var activeTableTab = "activeTableTab";
    @@ -139,46 +166,51 @@ var activeTableTab = "activeTableTab"; +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandConditions.html b/docs/acf-core/co/aikar/commands/CommandConditions.html index 2447bad1..a5022a85 100644 --- a/docs/acf-core/co/aikar/commands/CommandConditions.html +++ b/docs/acf-core/co/aikar/commands/CommandConditions.html @@ -1,12 +1,21 @@ - + - CommandConditions (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Class CommandConditions<I extends CommandIssuer,CEC extends CommandExecutionContext<CEC,I>,CC extends ConditionContext<I>>

    + +

    Class CommandConditions<I extends CommandIssuer,​CEC extends CommandExecutionContext<CEC,​I>,​CC extends ConditionContext<I>>

    @@ -107,9 +131,8 @@ var activeTableTab = "activeTableTab";
    @@ -117,61 +140,71 @@ extends
  • +
    +
    +
    +
  • @@ -179,53 +212,58 @@ extends
  • +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandContexts.html b/docs/acf-core/co/aikar/commands/CommandContexts.html index e0d78247..ebf606b5 100644 --- a/docs/acf-core/co/aikar/commands/CommandContexts.html +++ b/docs/acf-core/co/aikar/commands/CommandContexts.html @@ -1,12 +1,21 @@ - + - CommandContexts (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Class CommandContexts<R extends CommandExecutionContext<?,? extends CommandIssuer>>

    + +

    Class CommandContexts<R extends CommandExecutionContext<?,​? extends CommandIssuer>>

    @@ -117,93 +140,107 @@ extends
  • +
    +
    +
    +
  • @@ -211,130 +248,139 @@ extends
  • +
    +
    +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandExecutionContext.html b/docs/acf-core/co/aikar/commands/CommandExecutionContext.html index 637071ff..547da518 100644 --- a/docs/acf-core/co/aikar/commands/CommandExecutionContext.html +++ b/docs/acf-core/co/aikar/commands/CommandExecutionContext.html @@ -1,12 +1,21 @@ - + - CommandExecutionContext (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Class CommandExecutionContext<CEC extends CommandExecutionContext,I extends CommandIssuer>

    + +

    Class CommandExecutionContext<CEC extends CommandExecutionContext,​I extends CommandIssuer>

    @@ -107,9 +131,8 @@ var activeTableTab = "activeTableTab";
    @@ -117,217 +140,262 @@ extends
  • +
      -
    • +
    • Field Summary

      - +
      - + + - - + + +
      Fields 
      Modifier and TypeField and DescriptionFieldDescription
      protected Iissuer protected Iissuer 
    +
    +
    +
  • @@ -335,405 +403,414 @@ extends
  • +
    +
    +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandHelp.html b/docs/acf-core/co/aikar/commands/CommandHelp.html index a82c136b..22a8f1d3 100644 --- a/docs/acf-core/co/aikar/commands/CommandHelp.html +++ b/docs/acf-core/co/aikar/commands/CommandHelp.html @@ -1,12 +1,21 @@ - + - CommandHelp (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class CommandHelp

    @@ -117,131 +140,159 @@ extends
  • +
    +
    +
    +
  • @@ -249,237 +300,244 @@ extends
  • +
    +
    +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandHelpFormatter.html b/docs/acf-core/co/aikar/commands/CommandHelpFormatter.html index b11e6471..65e3dae0 100644 --- a/docs/acf-core/co/aikar/commands/CommandHelpFormatter.html +++ b/docs/acf-core/co/aikar/commands/CommandHelpFormatter.html @@ -1,12 +1,21 @@ - + - CommandHelpFormatter (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class CommandHelpFormatter

    @@ -117,137 +140,160 @@ extends
  • +
    +
    +
    +
  • @@ -255,172 +301,175 @@ extends
  • +
    +
    +
  • + diff --git a/docs/acf-core/co/aikar/commands/CommandParameter.html b/docs/acf-core/co/aikar/commands/CommandParameter.html index 20048f0b..caae3f3c 100644 --- a/docs/acf-core/co/aikar/commands/CommandParameter.html +++ b/docs/acf-core/co/aikar/commands/CommandParameter.html @@ -1,12 +1,21 @@ - + - CommandParameter (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Class CommandParameter<CEC extends CommandExecutionContext<CEC,? extends CommandIssuer>>

    + +

    Class CommandParameter<CEC extends CommandExecutionContext<CEC,​? extends CommandIssuer>>

    @@ -117,167 +140,204 @@ extends
  • +
    +
    +
    +
  • @@ -285,318 +345,325 @@ extends
  • +
    +
    +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/CommandReplacements.html b/docs/acf-core/co/aikar/commands/CommandReplacements.html index 0b25fefd..7a2a3539 100644 --- a/docs/acf-core/co/aikar/commands/CommandReplacements.html +++ b/docs/acf-core/co/aikar/commands/CommandReplacements.html @@ -1,12 +1,21 @@ - + - CommandReplacements (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class CommandReplacements

    @@ -159,56 +188,61 @@ extends
  • +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/ConditionContext.html b/docs/acf-core/co/aikar/commands/ConditionContext.html index 37addbf5..ced9f8a1 100644 --- a/docs/acf-core/co/aikar/commands/ConditionContext.html +++ b/docs/acf-core/co/aikar/commands/ConditionContext.html @@ -1,12 +1,21 @@ - + - ConditionContext (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    -

    Class ConditionContext<I extends CommandIssuer>

    + +

    Class ConditionContext<I extends CommandIssuer>

    @@ -117,49 +140,57 @@ extends
  • +
    +
  • @@ -167,75 +198,80 @@ extends
  • +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/ConditionFailedException.html b/docs/acf-core/co/aikar/commands/ConditionFailedException.html index 25995320..f7986121 100644 --- a/docs/acf-core/co/aikar/commands/ConditionFailedException.html +++ b/docs/acf-core/co/aikar/commands/ConditionFailedException.html @@ -1,12 +1,21 @@ - + - ConditionFailedException (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class ConditionFailedException

    @@ -195,12 +227,13 @@ extends
  • +
    +
  • +
    + diff --git a/docs/acf-core/co/aikar/commands/ExceptionHandler.html b/docs/acf-core/co/aikar/commands/ExceptionHandler.html index 614f5a23..8fe358a1 100644 --- a/docs/acf-core/co/aikar/commands/ExceptionHandler.html +++ b/docs/acf-core/co/aikar/commands/ExceptionHandler.html @@ -1,12 +1,21 @@ - + - ExceptionHandler (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Interface ExceptionHandler

    @@ -103,9 +127,8 @@ var activeTableTab = "activeTableTab";
    This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

    -
    -
    @FunctionalInterface
    -public interface ExceptionHandler
    +
    @FunctionalInterface
    +public interface ExceptionHandler
    Functional interface to allow plugins to handle uncaught excetpions
    @@ -114,24 +137,27 @@ public interface
  • +
      -
    • +
    • Method Summary

      - +
      - + + - + or other required elements. + thead: [ 1, "
      All Methods Instance Methods Abstract Methods 
      Modifier and TypeMethod and DescriptionMethodDescription
      booleanexecute(BaseCommand command, - RegisteredCommand registeredCommand, - CommandIssuer sender, - List<String> args, - Throwable t) +execute​(BaseCommand command, + RegisteredCommand registeredCommand, + CommandIssuer sender, + List<String> args, + Throwable t)
      Called when an exception occurs while executing a command
      If an exception handler properly handles an exception, the user will not be noticied by the framework that something went unexceptected.
      @@ -140,6 +166,7 @@ public interface
    • +
      + + diff --git a/docs/acf-core/co/aikar/commands/HelpEntry.html b/docs/acf-core/co/aikar/commands/HelpEntry.html index 5b5b33a6..844022d7 100644 --- a/docs/acf-core/co/aikar/commands/HelpEntry.html +++ b/docs/acf-core/co/aikar/commands/HelpEntry.html @@ -1,12 +1,21 @@ - + - HelpEntry (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class HelpEntry

      @@ -117,63 +140,75 @@ extends
    • +
      +
    • @@ -181,109 +216,114 @@ extends
    • +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/InvalidCommandArgument.html b/docs/acf-core/co/aikar/commands/InvalidCommandArgument.html index bca963f6..0215e8e0 100644 --- a/docs/acf-core/co/aikar/commands/InvalidCommandArgument.html +++ b/docs/acf-core/co/aikar/commands/InvalidCommandArgument.html @@ -1,12 +1,21 @@ - + - InvalidCommandArgument (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class InvalidCommandArgument

      @@ -211,12 +247,13 @@ extends
    • +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/InvalidCommandContextException.html b/docs/acf-core/co/aikar/commands/InvalidCommandContextException.html index 50d271a4..9a0a626c 100644 --- a/docs/acf-core/co/aikar/commands/InvalidCommandContextException.html +++ b/docs/acf-core/co/aikar/commands/InvalidCommandContextException.html @@ -1,12 +1,21 @@ - + - InvalidCommandContextException (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class InvalidCommandContextException

      +
      + diff --git a/docs/acf-core/co/aikar/commands/IssuerLocaleChangedCallback.html b/docs/acf-core/co/aikar/commands/IssuerLocaleChangedCallback.html index 89480a29..eb5082cc 100644 --- a/docs/acf-core/co/aikar/commands/IssuerLocaleChangedCallback.html +++ b/docs/acf-core/co/aikar/commands/IssuerLocaleChangedCallback.html @@ -1,12 +1,21 @@ - + - IssuerLocaleChangedCallback (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      -

      Interface IssuerLocaleChangedCallback<I extends CommandIssuer>

      + +

      Interface IssuerLocaleChangedCallback<I extends CommandIssuer>

      @@ -108,26 +131,30 @@ var activeTableTab = "activeTableTab";
      @@ -135,41 +162,46 @@ var activeTableTab = "activeTableTab"; +
      + diff --git a/docs/acf-core/co/aikar/commands/Locales.html b/docs/acf-core/co/aikar/commands/Locales.html index ed45dda9..46bacae0 100644 --- a/docs/acf-core/co/aikar/commands/Locales.html +++ b/docs/acf-core/co/aikar/commands/Locales.html @@ -1,12 +1,21 @@ - + - Locales (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class Locales

      @@ -117,257 +140,314 @@ extends
    • +
      +
      +
      +
      +
      +
    • @@ -375,487 +455,496 @@ extends
    • +
      +
      +
      +
      +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/MessageFormatter.html b/docs/acf-core/co/aikar/commands/MessageFormatter.html index 889ae9dd..6c0864c8 100644 --- a/docs/acf-core/co/aikar/commands/MessageFormatter.html +++ b/docs/acf-core/co/aikar/commands/MessageFormatter.html @@ -1,12 +1,21 @@ - + - MessageFormatter (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class MessageFormatter<FT>

      @@ -189,97 +224,104 @@ extends
    • +
      +
      +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/MessageKeys.html b/docs/acf-core/co/aikar/commands/MessageKeys.html index e02eb27e..4258d734 100644 --- a/docs/acf-core/co/aikar/commands/MessageKeys.html +++ b/docs/acf-core/co/aikar/commands/MessageKeys.html @@ -1,12 +1,21 @@ - + - MessageKeys (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Enum MessageKeys

      @@ -269,253 +326,256 @@ the order they are declared. +
      + diff --git a/docs/acf-core/co/aikar/commands/MessageType.html b/docs/acf-core/co/aikar/commands/MessageType.html index 3613e32c..786e6964 100644 --- a/docs/acf-core/co/aikar/commands/MessageType.html +++ b/docs/acf-core/co/aikar/commands/MessageType.html @@ -1,12 +1,21 @@ - + - MessageType (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class MessageType

      @@ -117,83 +140,99 @@ extends
    • +
      +
      +
        -
      • +
      • Constructor Summary

        - +
        - + + - + +
        Constructors 
        Constructor and DescriptionConstructorDescription
        MessageType() MessageType() 
      +
      +
      +
    • @@ -201,56 +240,59 @@ extends
    • +
      +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/RegisteredCommand.html b/docs/acf-core/co/aikar/commands/RegisteredCommand.html index f7a8b54f..5df0165f 100644 --- a/docs/acf-core/co/aikar/commands/RegisteredCommand.html +++ b/docs/acf-core/co/aikar/commands/RegisteredCommand.html @@ -1,12 +1,21 @@ - + - RegisteredCommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      -

      Class RegisteredCommand<CEC extends CommandExecutionContext<CEC,? extends CommandIssuer>>

      + +

      Class RegisteredCommand<CEC extends CommandExecutionContext<CEC,​? extends CommandIssuer>>

      @@ -117,100 +140,120 @@ extends
    • +
      +
      +
      +
    • @@ -218,168 +261,175 @@ extends
    • +
      +
      +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/RootCommand.html b/docs/acf-core/co/aikar/commands/RootCommand.html index bc2ef527..886c76c2 100644 --- a/docs/acf-core/co/aikar/commands/RootCommand.html +++ b/docs/acf-core/co/aikar/commands/RootCommand.html @@ -1,12 +1,21 @@ - + - RootCommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Interface RootCommand

      @@ -99,7 +123,6 @@ var activeTableTab = "activeTableTab"; @@ -108,97 +131,116 @@ var activeTableTab = "activeTableTab";
      @@ -206,189 +248,194 @@ var activeTableTab = "activeTableTab"; +
      + diff --git a/docs/acf-core/co/aikar/commands/ShowCommandHelp.html b/docs/acf-core/co/aikar/commands/ShowCommandHelp.html index 413ab4bf..f27a328e 100644 --- a/docs/acf-core/co/aikar/commands/ShowCommandHelp.html +++ b/docs/acf-core/co/aikar/commands/ShowCommandHelp.html @@ -1,12 +1,21 @@ - + - ShowCommandHelp (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class ShowCommandHelp

      +
      +
      +
      + diff --git a/docs/acf-core/co/aikar/commands/UnresolvedDependencyException.html b/docs/acf-core/co/aikar/commands/UnresolvedDependencyException.html index 448a780d..e720d08b 100644 --- a/docs/acf-core/co/aikar/commands/UnresolvedDependencyException.html +++ b/docs/acf-core/co/aikar/commands/UnresolvedDependencyException.html @@ -1,12 +1,21 @@ - + - UnresolvedDependencyException (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class UnresolvedDependencyException

      See Also:
      Serialized Form
      @@ -136,42 +159,47 @@ extends
    • +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/UnstableAPI.html b/docs/acf-core/co/aikar/commands/UnstableAPI.html index 2264a021..3a20ca8e 100644 --- a/docs/acf-core/co/aikar/commands/UnstableAPI.html +++ b/docs/acf-core/co/aikar/commands/UnstableAPI.html @@ -1,12 +1,21 @@ - + - UnstableAPI (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Annotation Type UnstableAPI

      @@ -91,26 +115,28 @@
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/CatchAll.html b/docs/acf-core/co/aikar/commands/annotation/CatchAll.html index f571c517..bb9cdaef 100644 --- a/docs/acf-core/co/aikar/commands/annotation/CatchAll.html +++ b/docs/acf-core/co/aikar/commands/annotation/CatchAll.html @@ -1,12 +1,21 @@ - + - CatchAll (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type CatchAll

      @@ -91,29 +115,31 @@
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/CatchUnknown.html b/docs/acf-core/co/aikar/commands/annotation/CatchUnknown.html index 926c98ce..05e5ede0 100644 --- a/docs/acf-core/co/aikar/commands/annotation/CatchUnknown.html +++ b/docs/acf-core/co/aikar/commands/annotation/CatchUnknown.html @@ -1,12 +1,21 @@ - + - CatchUnknown (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type CatchUnknown

      @@ -91,10 +115,9 @@
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/CommandCompletion.html b/docs/acf-core/co/aikar/commands/annotation/CommandCompletion.html index a0cb7294..cf25e202 100644 --- a/docs/acf-core/co/aikar/commands/annotation/CommandCompletion.html +++ b/docs/acf-core/co/aikar/commands/annotation/CommandCompletion.html @@ -1,12 +1,21 @@ - + - CommandCompletion (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type CommandCompletion

      @@ -91,20 +115,15 @@
      @@ -112,24 +131,28 @@ public @interface
    • +
        -
      • +
      • Required Element Summary

        - +
        - + + - - + + +
        Required Elements 
        Modifier and TypeRequired Element and DescriptionRequired ElementDescription
        Stringvalue Stringvalue 
      +
    • @@ -137,37 +160,42 @@ public @interface
    • +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/CommandPermission.html b/docs/acf-core/co/aikar/commands/annotation/CommandPermission.html index e972375a..1837190b 100644 --- a/docs/acf-core/co/aikar/commands/annotation/CommandPermission.html +++ b/docs/acf-core/co/aikar/commands/annotation/CommandPermission.html @@ -1,12 +1,21 @@ - + - CommandPermission (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type CommandPermission

      @@ -91,10 +115,9 @@
      @@ -130,37 +157,42 @@ public @interface
    • +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/Conditions.html b/docs/acf-core/co/aikar/commands/annotation/Conditions.html index 65a6e5dd..a4fb7314 100644 --- a/docs/acf-core/co/aikar/commands/annotation/Conditions.html +++ b/docs/acf-core/co/aikar/commands/annotation/Conditions.html @@ -1,12 +1,21 @@ - + - Conditions (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type Conditions

      @@ -91,18 +115,13 @@
      @@ -110,24 +129,28 @@ public @interface
    • +
        -
      • +
      • Required Element Summary

        - +
        - + + - - + + +
        Required Elements 
        Modifier and TypeRequired Element and DescriptionRequired ElementDescription
        Stringvalue Stringvalue 
      +
    • @@ -135,37 +158,42 @@ public @interface
    • +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/Default.html b/docs/acf-core/co/aikar/commands/annotation/Default.html index 5d579327..89f2eaa4 100644 --- a/docs/acf-core/co/aikar/commands/annotation/Default.html +++ b/docs/acf-core/co/aikar/commands/annotation/Default.html @@ -1,12 +1,21 @@ - + - Default (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type Default

      @@ -91,10 +115,9 @@
      @@ -129,18 +156,19 @@ public @interface
    • +
      +
    • + diff --git a/docs/acf-core/co/aikar/commands/annotation/HelpCommand.html b/docs/acf-core/co/aikar/commands/annotation/HelpCommand.html index ac70826b..71f2f937 100644 --- a/docs/acf-core/co/aikar/commands/annotation/HelpCommand.html +++ b/docs/acf-core/co/aikar/commands/annotation/HelpCommand.html @@ -1,12 +1,21 @@ - + - HelpCommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type HelpCommand

      @@ -91,14 +115,13 @@
      @@ -106,26 +129,30 @@ public @interface
    • +
        -
      • +
      • Optional Element Summary

        - +
        - + + - - + +
        Optional Elements 
        Modifier and TypeOptional Element and DescriptionOptional ElementDescription
        Stringvalue +Stringvalue
        The value to forward to the @Subcommand annotation.
      +
    • @@ -133,18 +160,19 @@ public @interface
    • +
        -
      • +
      • Element Detail

        - +
        • value

          -
          public abstract String value
          +
          String value
          The value to forward to the @Subcommand annotation. Lists which subcommands to register to trigger help
          Returns:
          @@ -157,21 +185,25 @@ public @interface + +

          Copyright © 2020. All rights reserved.

          + diff --git a/docs/acf-core/co/aikar/commands/annotation/HelpSearchTags.html b/docs/acf-core/co/aikar/commands/annotation/HelpSearchTags.html index d1b03db0..bc3a05e8 100644 --- a/docs/acf-core/co/aikar/commands/annotation/HelpSearchTags.html +++ b/docs/acf-core/co/aikar/commands/annotation/HelpSearchTags.html @@ -1,12 +1,21 @@ - + - HelpSearchTags (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
          + +
          +
          -
          co.aikar.commands.annotation
          +

          Annotation Type HelpSearchTags

          @@ -91,10 +115,9 @@
          @@ -131,37 +158,42 @@ public @interface
        • +
          +
        +
    • + diff --git a/docs/acf-core/co/aikar/commands/annotation/Optional.html b/docs/acf-core/co/aikar/commands/annotation/Optional.html index a4bbc131..8cb62f57 100644 --- a/docs/acf-core/co/aikar/commands/annotation/Optional.html +++ b/docs/acf-core/co/aikar/commands/annotation/Optional.html @@ -1,12 +1,21 @@ - + - Optional (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type Optional

      @@ -91,10 +115,9 @@
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/Private.html b/docs/acf-core/co/aikar/commands/annotation/Private.html index 81134e08..cb352d5d 100644 --- a/docs/acf-core/co/aikar/commands/annotation/Private.html +++ b/docs/acf-core/co/aikar/commands/annotation/Private.html @@ -1,12 +1,21 @@ - + - Private (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type Private

      @@ -91,26 +115,28 @@
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/Single.html b/docs/acf-core/co/aikar/commands/annotation/Single.html index bb3f8243..b81d0bd0 100644 --- a/docs/acf-core/co/aikar/commands/annotation/Single.html +++ b/docs/acf-core/co/aikar/commands/annotation/Single.html @@ -1,12 +1,21 @@ - + - Single (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type Single

      @@ -91,26 +115,28 @@
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/Split.html b/docs/acf-core/co/aikar/commands/annotation/Split.html index 9d913d07..b0acedc3 100644 --- a/docs/acf-core/co/aikar/commands/annotation/Split.html +++ b/docs/acf-core/co/aikar/commands/annotation/Split.html @@ -1,12 +1,21 @@ - + - Split (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type Split

      @@ -91,10 +115,9 @@
      @@ -129,18 +156,19 @@ public @interface
    • +
        -
      • +
      • Element Detail

        - +
        • value

          -
          public abstract String value
          +
          String value
          Default:
          ","
          @@ -149,21 +177,25 @@ public @interface + +

          Copyright © 2020. All rights reserved.

          + diff --git a/docs/acf-core/co/aikar/commands/annotation/Subcommand.html b/docs/acf-core/co/aikar/commands/annotation/Subcommand.html index 2ad55b81..b7908c8e 100644 --- a/docs/acf-core/co/aikar/commands/annotation/Subcommand.html +++ b/docs/acf-core/co/aikar/commands/annotation/Subcommand.html @@ -1,12 +1,21 @@ - + - Subcommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
          + +
          +
          -
          co.aikar.commands.annotation
          +

          Annotation Type Subcommand

          @@ -91,15 +115,14 @@
        @@ -107,24 +130,28 @@ public @interface
      • +
          -
        • +
        • Required Element Summary

          - +
          - + + - - + + +
          Required Elements 
          Modifier and TypeRequired Element and DescriptionRequired ElementDescription
          Stringvalue Stringvalue 
        +
      @@ -132,37 +159,42 @@ public @interface
    • +
      +
    • +
    • + diff --git a/docs/acf-core/co/aikar/commands/annotation/Syntax.html b/docs/acf-core/co/aikar/commands/annotation/Syntax.html index 086416a1..bb514f27 100644 --- a/docs/acf-core/co/aikar/commands/annotation/Syntax.html +++ b/docs/acf-core/co/aikar/commands/annotation/Syntax.html @@ -1,12 +1,21 @@ - + - Syntax (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type Syntax

      @@ -91,17 +115,16 @@
    • @@ -109,24 +132,28 @@ public @interface
    • +
        -
      • +
      • Required Element Summary

        - +
        - + + - - + + +
        Required Elements 
        Modifier and TypeRequired Element and DescriptionRequired ElementDescription
        Stringvalue Stringvalue 
      +
    • @@ -134,37 +161,42 @@ public @interface
    • +
      +
    • + + diff --git a/docs/acf-core/co/aikar/commands/annotation/UnknownHandler.html b/docs/acf-core/co/aikar/commands/annotation/UnknownHandler.html index 6931a4c2..5f739ed7 100644 --- a/docs/acf-core/co/aikar/commands/annotation/UnknownHandler.html +++ b/docs/acf-core/co/aikar/commands/annotation/UnknownHandler.html @@ -1,12 +1,21 @@ - + - UnknownHandler (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type UnknownHandler

      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/Values.html b/docs/acf-core/co/aikar/commands/annotation/Values.html index d99f68d1..ac9de50b 100644 --- a/docs/acf-core/co/aikar/commands/annotation/Values.html +++ b/docs/acf-core/co/aikar/commands/annotation/Values.html @@ -1,12 +1,21 @@ - + - Values (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.annotation
      +

      Annotation Type Values

      @@ -91,13 +115,12 @@
      @@ -105,24 +128,28 @@ public @interface
    • +
        -
      • +
      • Required Element Summary

        - +
        - + + - - + + +
        Required Elements 
        Modifier and TypeRequired Element and DescriptionRequired ElementDescription
        Stringvalue Stringvalue 
      +
    • @@ -130,37 +157,42 @@ public @interface
    • +
      +
    • +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/CatchAll.html b/docs/acf-core/co/aikar/commands/annotation/class-use/CatchAll.html index fbbb9152..4db8ed71 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/CatchAll.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/CatchAll.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.CatchAll (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.CatchAll

      No usage of co.aikar.commands.annotation.CatchAll
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/CatchUnknown.html b/docs/acf-core/co/aikar/commands/annotation/class-use/CatchUnknown.html index 1405f703..f9e078f9 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/CatchUnknown.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/CatchUnknown.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.CatchUnknown (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.CatchUnknown

      No usage of co.aikar.commands.annotation.CatchUnknown
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/CommandAlias.html b/docs/acf-core/co/aikar/commands/annotation/class-use/CommandAlias.html index 4539e5d1..75b43d98 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/CommandAlias.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/CommandAlias.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.CommandAlias (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.CommandAlias

      No usage of co.aikar.commands.annotation.CommandAlias
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/CommandCompletion.html b/docs/acf-core/co/aikar/commands/annotation/class-use/CommandCompletion.html index 0f7cde79..ea30780f 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/CommandCompletion.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/CommandCompletion.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.CommandCompletion (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.CommandCompletion

      No usage of co.aikar.commands.annotation.CommandCompletion
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/CommandPermission.html b/docs/acf-core/co/aikar/commands/annotation/class-use/CommandPermission.html index 275a0b86..e0cdcc30 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/CommandPermission.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/CommandPermission.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.CommandPermission (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.CommandPermission

      No usage of co.aikar.commands.annotation.CommandPermission
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Conditions.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Conditions.html index 3747dfd0..d85be8de 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Conditions.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Conditions.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Conditions (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Conditions

      No usage of co.aikar.commands.annotation.Conditions
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Default.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Default.html index 9e66a63e..c0691cf2 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Default.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Default.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Default (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Default

      No usage of co.aikar.commands.annotation.Default
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Dependency.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Dependency.html index 3ad50b75..427757a1 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Dependency.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Dependency.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Dependency (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Dependency

      No usage of co.aikar.commands.annotation.Dependency
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Description.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Description.html index fa082047..b547242e 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Description.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Description.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Description (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Description

      No usage of co.aikar.commands.annotation.Description
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Flags.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Flags.html index 2430b9db..a8ea3198 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Flags.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Flags.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Flags (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Flags

      No usage of co.aikar.commands.annotation.Flags
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/HelpCommand.html b/docs/acf-core/co/aikar/commands/annotation/class-use/HelpCommand.html index ae5af849..d6e5c0fe 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/HelpCommand.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/HelpCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.HelpCommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.HelpCommand

      No usage of co.aikar.commands.annotation.HelpCommand
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/HelpSearchTags.html b/docs/acf-core/co/aikar/commands/annotation/class-use/HelpSearchTags.html index 5691b954..b861f4f0 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/HelpSearchTags.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/HelpSearchTags.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.HelpSearchTags (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.HelpSearchTags

      No usage of co.aikar.commands.annotation.HelpSearchTags
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Optional.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Optional.html index 6d702d26..9d767f55 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Optional.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Optional.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Optional (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Optional

      No usage of co.aikar.commands.annotation.Optional
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/PreCommand.html b/docs/acf-core/co/aikar/commands/annotation/class-use/PreCommand.html index 180ddc3f..03548ba8 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/PreCommand.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/PreCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.PreCommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.PreCommand

      No usage of co.aikar.commands.annotation.PreCommand
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Private.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Private.html index b50b522b..affda0bc 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Private.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Private.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Private (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Private

      No usage of co.aikar.commands.annotation.Private
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Single.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Single.html index 864c00df..2381426f 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Single.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Single.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Single (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Single

      No usage of co.aikar.commands.annotation.Single
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Split.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Split.html index dd3ca5e1..42530f6d 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Split.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Split.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Split (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Split

      No usage of co.aikar.commands.annotation.Split
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Subcommand.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Subcommand.html index f4a6efb4..11cafdda 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Subcommand.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Subcommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Subcommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Subcommand

      No usage of co.aikar.commands.annotation.Subcommand
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Syntax.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Syntax.html index 37980a46..c92cae83 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Syntax.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Syntax.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Syntax (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Syntax

      No usage of co.aikar.commands.annotation.Syntax
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/UnknownHandler.html b/docs/acf-core/co/aikar/commands/annotation/class-use/UnknownHandler.html index e4df5ef7..de9eb130 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/UnknownHandler.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/UnknownHandler.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.UnknownHandler (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.UnknownHandler

      No usage of co.aikar.commands.annotation.UnknownHandler
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/class-use/Values.html b/docs/acf-core/co/aikar/commands/annotation/class-use/Values.html index 9103e99f..0f53728f 100644 --- a/docs/acf-core/co/aikar/commands/annotation/class-use/Values.html +++ b/docs/acf-core/co/aikar/commands/annotation/class-use/Values.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Values (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.annotation.Values

      No usage of co.aikar.commands.annotation.Values
      +
      + diff --git a/docs/acf-core/co/aikar/commands/annotation/package-summary.html b/docs/acf-core/co/aikar/commands/annotation/package-summary.html index c474758a..6fd83d74 100644 --- a/docs/acf-core/co/aikar/commands/annotation/package-summary.html +++ b/docs/acf-core/co/aikar/commands/annotation/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.annotation (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Package co.aikar.commands.annotation

      +
      @@ -231,18 +269,19 @@ var activeTableTab = "activeTableTab";
      • +
          -
        • +
        • Method Detail

          - +
          • getCause

            -
            Throwable getCause()
            +
            Throwable getCause()
            Returns the reference to the exception or error that caused the exception implementing the Nestable to be thrown.
            @@ -251,13 +290,13 @@ var activeTableTab = "activeTableTab";
          - +
          • getMessage

            -
            String getMessage()
            +
            String getMessage()
            Returns the error message of this and any nested Throwable.
            @@ -266,13 +305,13 @@ var activeTableTab = "activeTableTab";
          - +
          • getMessage

            -
            String getMessage(int index)
            +
            String getMessage​(int index)
            Returns the error message of the Throwable in the chain of Throwables at the specified index, numbered from 0.
            @@ -283,24 +322,24 @@ var activeTableTab = "activeTableTab";
            the error message, or null if the Throwable at the specified index in the chain does not contain a message
            Throws:
            -
            IndexOutOfBoundsException - if the index argument is +
            IndexOutOfBoundsException - if the index argument is negative or not less than the count of Throwables in the chain
          - +
          • getMessages

            -
            String[] getMessages()
            +
            String[] getMessages()
            Returns the error message of this and any nested Throwables in an array of Strings, one element for each message. Any Throwable not containing a message is represented in the array by a null. This has the effect of cause the length of the returned - array to be equal to the result of the getThrowableCount() + array to be equal to the result of the getThrowableCount() operation.
            Returns:
            @@ -308,13 +347,13 @@ var activeTableTab = "activeTableTab";
          - + - +
          • getThrowableCount

            -
            int getThrowableCount()
            +
            int getThrowableCount()
            Returns the number of nested Throwables represented by this Nestable, including this Nestable.
            @@ -345,13 +384,13 @@ var activeTableTab = "activeTableTab";
          - +
          • getThrowables

            -
            Throwable[] getThrowables()
            +
            Throwable[] getThrowables()
            Returns this Nestable and any nested Throwables in an array of Throwables, one element for each Throwable.
            @@ -361,13 +400,13 @@ var activeTableTab = "activeTableTab";
          - +
          • indexOfThrowable

            -
            int indexOfThrowable(Class type)
            +
            int indexOfThrowable​(Class type)
            Returns the index, numbered from 0, of the first occurrence of the specified type, or a subclass, in the chain of Throwables. The method returns -1 if the specified type is not found in the chain. @@ -385,13 +424,13 @@ var activeTableTab = "activeTableTab";
          - +
          • indexOfThrowable

            -
            int indexOfThrowable(Class type,
            +
            int indexOfThrowable​(Class type,
                                  int fromIndex)
            Returns the index, numbered from 0, of the first Throwable that matches the specified type, or a subclass, in the chain of Throwables @@ -411,19 +450,19 @@ var activeTableTab = "activeTableTab";
            index of the first occurrence of the type in the chain, or -1 if the type is not found
            Throws:
            -
            IndexOutOfBoundsException - if the fromIndex argument +
            IndexOutOfBoundsException - if the fromIndex argument is negative or not less than the count of Throwables in the chain
          - +
          • printStackTrace

            -
            void printStackTrace(PrintWriter out)
            +
            void printStackTrace​(PrintWriter out)
            Prints the stack trace of this exception to the specified print writer. Includes information from the exception, if any, which caused this exception.
            @@ -433,13 +472,13 @@ var activeTableTab = "activeTableTab";
          - +
          • printStackTrace

            -
            void printStackTrace(PrintStream out)
            +
            void printStackTrace​(PrintStream out)
            Prints the stack trace of this exception to the specified print stream. Includes information from the exception, if any, which caused this exception.
            @@ -449,13 +488,13 @@ var activeTableTab = "activeTableTab";
          - +
          • printPartialStackTrace

            -
            void printPartialStackTrace(PrintWriter out)
            +
            void printPartialStackTrace​(PrintWriter out)
            Prints the stack trace for this exception only--root cause not included--using the provided writer. Used by individual stack traces to a buffer. The implementation of @@ -469,21 +508,25 @@ var activeTableTab = "activeTableTab";
        +
      +
      + diff --git a/docs/acf-core/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.html b/docs/acf-core/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.html index 4518cc89..6274eb21 100644 --- a/docs/acf-core/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.html +++ b/docs/acf-core/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.html @@ -1,12 +1,21 @@ - + - ApacheCommonsExceptionUtil (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands.apachecommonslang
      +

      Class ApacheCommonsExceptionUtil

        -
      • java.lang.Object
      • +
      • java.lang.Object
        • co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil
        • @@ -107,9 +131,8 @@ var activeTableTab = "activeTableTab";

          • -
            public class ApacheCommonsExceptionUtil
            -extends Object
            +extends Object

            Provides utilities for manipulating and examining Throwable objects.

            @@ -127,21 +150,24 @@ extends
          • +
              -
            • +
            • Nested Class Summary

              - +
              - + + - + @@ -149,19 +175,23 @@ extends
                -
              • +
              • Constructor Summary

                -
              Nested Classes 
              Modifier and TypeClass and DescriptionClassDescription
              static interface ApacheCommonsExceptionUtil.Nestable -
              An interface to be implemented by Throwable +
              ApacheCommonsExceptionUtil.Nestable +
              An interface to be implemented by Throwable extensions which would like to be able to nest root exceptions inside themselves.
              +
              - + + - + or other required elements. + thead: [ 1, "
              Constructors 
              Constructor and DescriptionConstructorDescription
              ApacheCommonsExceptionUtil() +ApacheCommonsExceptionUtil()
              Public constructor allows an instance of ExceptionUtils to be created, although that is not normally necessary.
              @@ -170,90 +200,104 @@ extends + @@ -335,12 +388,13 @@ extends
            • +
                -
              • +
              • Constructor Detail

                - +
                  @@ -355,19 +409,21 @@ extends
                    -
                  • +
                  • Method Detail

                    - +
                    • addCauseMethodName

                      -
                      public static void addCauseMethodName(String methodName)
                      +
                      public static void addCauseMethodName​(String methodName)

                      Adds to the list of method names used in the search for Throwable objects.

                      @@ -379,13 +435,13 @@ extends +
                      • removeCauseMethodName

                        -
                        public static void removeCauseMethodName(String methodName)
                        +
                        public static void removeCauseMethodName​(String methodName)

                        Removes from the list of method names used in the search for Throwable objects.

                        @@ -397,14 +453,14 @@ extends +
                        • setCause

                          -
                          public static boolean setCause(Throwable target,
                          -                               Throwable cause)
                          +
                          public static boolean setCause​(Throwable target,
                          +                               Throwable cause)

                          Sets the cause of a Throwable using introspection, allowing source code compatibility between pre-1.4 and post-1.4 Java releases.

                          @@ -437,13 +493,13 @@ extends + - +
                          • getThrowableList

                            -
                            public static List getThrowableList(Throwable throwable)
                            +
                            public static List getThrowableList​(Throwable throwable)

                            Returns the list of Throwable objects in the exception chain.

                            @@ -679,18 +735,18 @@ extends +
                            • indexOfThrowable

                              -
                              public static int indexOfThrowable(Throwable throwable,
                              -                                   Class clazz)
                              +
                              public static int indexOfThrowable​(Throwable throwable,
                              +                                   Class clazz)

                              Returns the (zero based) index of the first Throwable that matches the specified class (exactly) in the exception chain. Subclasses of the specified class do not match - see - indexOfType(Throwable, Class) for the opposite.

                              + indexOfType(Throwable, Class) for the opposite.

                              A null throwable returns -1. A null type returns -1. @@ -704,20 +760,20 @@ extends +

                              • indexOfThrowable

                                -
                                public static int indexOfThrowable(Throwable throwable,
                                -                                   Class clazz,
                                +
                                public static int indexOfThrowable​(Throwable throwable,
                                +                                   Class clazz,
                                                                    int fromIndex)

                                Returns the (zero based) index of the first Throwable that matches the specified type in the exception chain from a specified index. Subclasses of the specified class do not match - see - indexOfType(Throwable, Class, int) for the opposite.

                                + indexOfType(Throwable, Class, int) for the opposite.

                                A null throwable returns -1. A null type returns -1. @@ -735,18 +791,18 @@ extends +

                                • indexOfType

                                  -
                                  public static int indexOfType(Throwable throwable,
                                  -                              Class type)
                                  +
                                  public static int indexOfType​(Throwable throwable,
                                  +                              Class type)

                                  Returns the (zero based) index of the first Throwable that matches the specified class or subclass in the exception chain. Subclasses of the specified class do match - see - indexOfThrowable(Throwable, Class) for the opposite.

                                  + indexOfThrowable(Throwable, Class) for the opposite.

                                  A null throwable returns -1. A null type returns -1. @@ -762,20 +818,20 @@ extends +

                                  • indexOfType

                                    -
                                    public static int indexOfType(Throwable throwable,
                                    -                              Class type,
                                    +
                                    public static int indexOfType​(Throwable throwable,
                                    +                              Class type,
                                                                   int fromIndex)

                                    Returns the (zero based) index of the first Throwable that matches the specified type in the exception chain from a specified index. Subclasses of the specified class do match - see - indexOfThrowable(Throwable, Class) for the opposite.

                                    + indexOfThrowable(Throwable, Class) for the opposite.

                                    A null throwable returns -1. A null type returns -1. @@ -795,33 +851,33 @@ extends +

                                    - +
                                    • getFullStackTrace

                                      -
                                      public static String getFullStackTrace(Throwable throwable)
                                      +
                                      public static String getFullStackTrace​(Throwable throwable)

                                      A way to get the entire nested stack-trace of an throwable.

                                      The result of this method is highly dependent on the JDK version @@ -836,17 +892,17 @@ extends +

                                      • getStackTrace

                                        -
                                        public static String getStackTrace(Throwable throwable)
                                        +
                                        public static String getStackTrace​(Throwable throwable)

                                        Gets the stack trace from a Throwable as a String.

                                        The result of this method vary by JDK version as this method - uses Throwable.printStackTrace(java.io.PrintWriter). + uses Throwable.printStackTrace(java.io.PrintWriter). On JDK1.3 and earlier, the cause exception will not be shown unless the specified throwable alters printStackTrace.

                                        @@ -860,21 +916,25 @@ extends + +

                                        Copyright © 2020. All rights reserved.

                                        + diff --git a/docs/acf-core/co/aikar/commands/apachecommonslang/ApacheCommonsLangUtil.html b/docs/acf-core/co/aikar/commands/apachecommonslang/ApacheCommonsLangUtil.html index ed0c752e..a7c910af 100644 --- a/docs/acf-core/co/aikar/commands/apachecommonslang/ApacheCommonsLangUtil.html +++ b/docs/acf-core/co/aikar/commands/apachecommonslang/ApacheCommonsLangUtil.html @@ -1,12 +1,21 @@ - + - ApacheCommonsLangUtil (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                                        + +
                                        +
                                        -
                                        co.aikar.commands.apachecommonslang
                                        +

                                        Class ApacheCommonsLangUtil

                                          -
                                        • java.lang.Object
                                        • +
                                        • java.lang.Object
                                          • co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil
                                          • @@ -107,9 +131,8 @@ var activeTableTab = "activeTableTab";

                                            • -
                                              -
                                              public class ApacheCommonsLangUtil
                                              -extends Object
                                              +
                                              public class ApacheCommonsLangUtil
                                              +extends Object
                                              Select methods copied from Apache Commons to avoid importing entire lib No changes to logic
                                            • @@ -119,93 +142,109 @@ extends
                                            • +
                                              +
                                              +
                                              +
                                              +
                                                -
                                              • +
                                              • Method Summary

                                                - +
                                                - + + - + - - + + - - + + - - + + - - + + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - +
                                                All Methods Static Methods Concrete Methods 
                                                Modifier and TypeMethod and DescriptionMethodDescription
                                                static <T> T[]addAll(T[] array1, - T... array2) +addAll​(T[] array1, + T... array2)
                                                Adds all the elements of the given arrays into a new array.
                                                static Stringcapitalize(String str) +static Stringcapitalize​(String str)
                                                Capitalizes all the whitespace separated words in a String.
                                                static Stringcapitalize(String str, - char... delimiters) +static Stringcapitalize​(String str, + char... delimiters)
                                                Capitalizes all the delimiter separated words in a String.
                                                static StringcapitalizeFully(String str) +static StringcapitalizeFully​(String str)
                                                Converts all the whitespace separated words in a String into capitalized words, that is each word is made up of a titlecase character and then a series of lowercase characters.
                                                static StringcapitalizeFully(String str, - char... delimiters) +static StringcapitalizeFully​(String str, + char... delimiters)
                                                Converts all the delimiter separated words in a String into capitalized words, that is each word is made up of a titlecase character and then a series of lowercase characters.
                                                @@ -213,264 +252,295 @@ extends
                                                static <T> T[]clone(T[] array) +clone​(T[] array)
                                                Shallow clones an array returning a typecast result and handling null.
                                                static intindexOf(Object[] array, - Object objectToFind) +indexOf​(Object[] array, + Object objectToFind)
                                                Finds the index of the given object in the array.
                                                static intindexOf(Object[] array, - Object objectToFind, - int startIndex) +indexOf​(Object[] array, + Object objectToFind, + int startIndex)
                                                Finds the index of the given object in the array starting at the given index.
                                                static booleanisDelimiter(char ch, - char[] delimiters) +isDelimiter​(char ch, + char[] delimiters)
                                                Is the character a delimiter.
                                                static booleanisNumeric(CharSequence cs) +isNumeric​(CharSequence cs)
                                                Checks if the CharSequence contains only Unicode digits.
                                                static Stringjoin(byte[] array, - char separator) +static Stringjoin​(byte[] array, + char separator)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(byte[] array, +static Stringjoin​(byte[] array, char separator, int startIndex, - int endIndex) + int endIndex)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(char[] array, - char separator) +static Stringjoin​(char[] array, + char separator)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(char[] array, +static Stringjoin​(char[] array, char separator, int startIndex, - int endIndex) + int endIndex)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(double[] array, - char separator) +static Stringjoin​(double[] array, + char separator)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(double[] array, +static Stringjoin​(double[] array, char separator, int startIndex, - int endIndex) + int endIndex)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(float[] array, - char separator) +static Stringjoin​(float[] array, + char separator)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(float[] array, +static Stringjoin​(float[] array, char separator, int startIndex, - int endIndex) + int endIndex)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(int[] array, - char separator) +static Stringjoin​(int[] array, + char separator)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(int[] array, +static Stringjoin​(int[] array, char separator, int startIndex, - int endIndex) + int endIndex)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(Iterable<?> iterable, - char separator) -
                                                Joins the elements of the provided Iterable into - a single String containing the provided elements.
                                                +
                                                static Stringjoin​(long[] array, + char separator) +
                                                + Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(Iterable<?> iterable, - String separator) +static Stringjoin​(long[] array, + char separator, + int startIndex, + int endIndex) +
                                                + Joins the elements of the provided array into a single String containing the provided list of elements.
                                                +
                                                static Stringjoin​(short[] array, + char separator) +
                                                + Joins the elements of the provided array into a single String containing the provided list of elements.
                                                +
                                                static Stringjoin​(short[] array, + char separator, + int startIndex, + int endIndex) +
                                                + Joins the elements of the provided array into a single String containing the provided list of elements.
                                                +
                                                static Stringjoin​(Iterable<?> iterable, + char separator)
                                                Joins the elements of the provided Iterable into a single String containing the provided elements.
                                                static Stringjoin(Iterator<?> iterator, - char separator) -
                                                Joins the elements of the provided Iterator into - a single String containing the provided elements.
                                                -
                                                static Stringjoin(Iterator<?> iterator, - String separator) -
                                                Joins the elements of the provided Iterator into - a single String containing the provided elements.
                                                -
                                                static Stringjoin(long[] array, - char separator) -
                                                - Joins the elements of the provided array into a single String containing the provided list of elements.
                                                -
                                                static Stringjoin(long[] array, - char separator, - int startIndex, - int endIndex) -
                                                - Joins the elements of the provided array into a single String containing the provided list of elements.
                                                +
                                                static Stringjoin​(Iterable<?> iterable, + String separator) +
                                                Joins the elements of the provided Iterable into + a single String containing the provided elements.
                                                static Stringjoin(Object[] array, - char separator) +static Stringjoin​(Object[] array, + char separator)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(Object[] array, +static Stringjoin​(Object[] array, char separator, int startIndex, - int endIndex) + int endIndex)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(Object[] array, - String separator) +static Stringjoin​(Object[] array, + String separator)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(Object[] array, - String separator, +static Stringjoin​(Object[] array, + String separator, int startIndex, - int endIndex) + int endIndex)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static Stringjoin(short[] array, - char separator) -
                                                - Joins the elements of the provided array into a single String containing the provided list of elements.
                                                +
                                                static Stringjoin​(Iterator<?> iterator, + char separator) +
                                                Joins the elements of the provided Iterator into + a single String containing the provided elements.
                                                static Stringjoin(short[] array, - char separator, - int startIndex, - int endIndex) -
                                                - Joins the elements of the provided array into a single String containing the provided list of elements.
                                                +
                                                static Stringjoin​(Iterator<?> iterator, + String separator) +
                                                Joins the elements of the provided Iterator into + a single String containing the provided elements.
                                                static <T> Stringjoin(T... elements) +static <T> Stringjoin​(T... elements)
                                                Joins the elements of the provided array into a single String containing the provided list of elements.
                                                static booleanstartsWith(CharSequence str, - CharSequence prefix) +startsWith​(CharSequence str, + CharSequence prefix)
                                                Check if a CharSequence starts with a specified prefix.
                                                static booleanstartsWithIgnoreCase(CharSequence str, - CharSequence prefix) +startsWithIgnoreCase​(CharSequence str, + CharSequence prefix)
                                                Case insensitive check if a CharSequence starts with a specified prefix.
                                              +
                                        @@ -478,18 +548,19 @@ extends
                                      • +
                                          -
                                        • +
                                        • Field Detail

                                          - +
                                          • EMPTY

                                            -
                                            public static final String EMPTY
                                            +
                                            public static final String EMPTY
                                            The empty String "".
                                            Since:
                                            @@ -499,16 +570,16 @@ extends +
                                            • INDEX_NOT_FOUND

                                              -
                                              public static final int INDEX_NOT_FOUND
                                              +
                                              public static final int INDEX_NOT_FOUND
                                              The index value when an element is not found in a list or array: -1. This value is returned by methods in this class and can also be used in comparisons with values returned by - various method from List.
                                              + various method from List.
                                      See Also:
                                      Constant Field Values
                                      @@ -517,38 +588,42 @@ extends +
              +
            • + + diff --git a/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsExceptionUtil.Nestable.html b/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsExceptionUtil.Nestable.html index 620d51eb..1862608d 100644 --- a/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsExceptionUtil.Nestable.html +++ b/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsExceptionUtil.Nestable.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil.Nestable (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Interface
              co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil.Nestable

              No usage of co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil.Nestable
              +
              + diff --git a/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsExceptionUtil.html b/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsExceptionUtil.html index c1a84921..0a036054 100644 --- a/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsExceptionUtil.html +++ b/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsExceptionUtil.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil

              No usage of co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil
              +
              + diff --git a/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsLangUtil.html b/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsLangUtil.html index 576da6b9..0cd2ccdd 100644 --- a/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsLangUtil.html +++ b/docs/acf-core/co/aikar/commands/apachecommonslang/class-use/ApacheCommonsLangUtil.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil

              No usage of co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil
              +
              + diff --git a/docs/acf-core/co/aikar/commands/apachecommonslang/package-summary.html b/docs/acf-core/co/aikar/commands/apachecommonslang/package-summary.html index 9c586883..cdd98fcf 100644 --- a/docs/acf-core/co/aikar/commands/apachecommonslang/package-summary.html +++ b/docs/acf-core/co/aikar/commands/apachecommonslang/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.apachecommonslang (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Package co.aikar.commands.apachecommonslang

              • - +
                @@ -82,9 +106,9 @@ - + @@ -93,7 +117,7 @@
                Interface Summary 
                Interface
                ApacheCommonsExceptionUtil.NestableApacheCommonsExceptionUtil.Nestable -
                An interface to be implemented by Throwable +
                An interface to be implemented by Throwable extensions which would like to be able to nest root exceptions inside themselves.
              • - +
                @@ -101,14 +125,14 @@ - + - + or other required elements. + thead: [ 1, "
                Class Summary 
                Class
                ApacheCommonsExceptionUtilApacheCommonsExceptionUtil
                Provides utilities for manipulating and examining Throwable objects.
                ApacheCommonsLangUtilApacheCommonsLangUtil
                Select methods copied from Apache Commons to avoid importing entire lib No changes to logic
                @@ -119,16 +143,19 @@ + + diff --git a/docs/acf-core/co/aikar/commands/apachecommonslang/package-tree.html b/docs/acf-core/co/aikar/commands/apachecommonslang/package-tree.html index d6a248b7..bb90b7c9 100644 --- a/docs/acf-core/co/aikar/commands/apachecommonslang/package-tree.html +++ b/docs/acf-core/co/aikar/commands/apachecommonslang/package-tree.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.apachecommonslang Class Hierarchy (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Hierarchy For Package co.aikar.commands.apachecommonslang

                Package Hierarchies: @@ -76,30 +100,37 @@
                +

                Class Hierarchy

                +
                +

                Interface Hierarchy

                +
                +
                + diff --git a/docs/acf-core/co/aikar/commands/apachecommonslang/package-use.html b/docs/acf-core/co/aikar/commands/apachecommonslang/package-use.html index ff5b198f..582198f9 100644 --- a/docs/acf-core/co/aikar/commands/apachecommonslang/package-use.html +++ b/docs/acf-core/co/aikar/commands/apachecommonslang/package-use.html @@ -1,12 +1,21 @@ - + - Uses of Package co.aikar.commands.apachecommonslang (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Package
                co.aikar.commands.apachecommonslang

                No usage of co.aikar.commands.apachecommonslang
                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/ACFUtil.html b/docs/acf-core/co/aikar/commands/class-use/ACFUtil.html index 7f43f69b..3438282c 100644 --- a/docs/acf-core/co/aikar/commands/class-use/ACFUtil.html +++ b/docs/acf-core/co/aikar/commands/class-use/ACFUtil.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ACFUtil (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.ACFUtil

                No usage of co.aikar.commands.ACFUtil
                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/AnnotationProcessor.html b/docs/acf-core/co/aikar/commands/class-use/AnnotationProcessor.html index 6f5bbd80..a1a08796 100644 --- a/docs/acf-core/co/aikar/commands/class-use/AnnotationProcessor.html +++ b/docs/acf-core/co/aikar/commands/class-use/AnnotationProcessor.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.AnnotationProcessor (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.AnnotationProcessor

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/BaseCommand.html b/docs/acf-core/co/aikar/commands/class-use/BaseCommand.html index 621a68ec..bb220ddb 100644 --- a/docs/acf-core/co/aikar/commands/class-use/BaseCommand.html +++ b/docs/acf-core/co/aikar/commands/class-use/BaseCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.BaseCommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.BaseCommand

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandCompletionContext.html b/docs/acf-core/co/aikar/commands/class-use/CommandCompletionContext.html index 3fb6c652..9fedfcbb 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandCompletionContext.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandCompletionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandCompletionContext (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandCompletionContext

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.AsyncCommandCompletionHandler.html b/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.AsyncCommandCompletionHandler.html index 455e3c27..2565002f 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.AsyncCommandCompletionHandler.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.AsyncCommandCompletionHandler.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.CommandCompletions.AsyncCommandCompletionHandler (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.CommandCompletions.AsyncCommandCompletionHandler

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.CommandCompletionHandler.html b/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.CommandCompletionHandler.html index 2be3984c..f78e2d7a 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.CommandCompletionHandler.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.CommandCompletionHandler.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.CommandCompletions.CommandCompletionHandler (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.CommandCompletions.CommandCompletionHandler

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.SyncCompletionRequired.html b/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.SyncCompletionRequired.html index 9f20d00b..ebeda1ed 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.SyncCompletionRequired.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.SyncCompletionRequired.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandCompletions.SyncCompletionRequired (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandCompletions.SyncCompletionRequired

                No usage of co.aikar.commands.CommandCompletions.SyncCompletionRequired
                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.html b/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.html index 96228fdc..34479525 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandCompletions.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandCompletions (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandCompletions

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandConditions.Condition.html b/docs/acf-core/co/aikar/commands/class-use/CommandConditions.Condition.html index 02100973..4a51dd45 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandConditions.Condition.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandConditions.Condition.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.CommandConditions.Condition (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.CommandConditions.Condition

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandConditions.ParameterCondition.html b/docs/acf-core/co/aikar/commands/class-use/CommandConditions.ParameterCondition.html index b481c30d..78684199 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandConditions.ParameterCondition.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandConditions.ParameterCondition.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.CommandConditions.ParameterCondition (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.CommandConditions.ParameterCondition

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandConditions.html b/docs/acf-core/co/aikar/commands/class-use/CommandConditions.html index 66c2f248..dd4571bf 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandConditions.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandConditions.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandConditions (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandConditions

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandContexts.html b/docs/acf-core/co/aikar/commands/class-use/CommandContexts.html index 640efe18..f3dc405c 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandContexts.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandContexts.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandContexts (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandContexts

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandExecutionContext.html b/docs/acf-core/co/aikar/commands/class-use/CommandExecutionContext.html index ce11cfb6..1e2b6080 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandExecutionContext.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandExecutionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandExecutionContext (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandExecutionContext

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandHelp.html b/docs/acf-core/co/aikar/commands/class-use/CommandHelp.html index abcb3e59..b49eeba5 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandHelp.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandHelp.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandHelp (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandHelp

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandHelpFormatter.html b/docs/acf-core/co/aikar/commands/class-use/CommandHelpFormatter.html index 2b2f5441..aa702006 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandHelpFormatter.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandHelpFormatter.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandHelpFormatter (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandHelpFormatter

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandIssuer.html b/docs/acf-core/co/aikar/commands/class-use/CommandIssuer.html index 84ec62f8..646d925f 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandIssuer.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandIssuer.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.CommandIssuer (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.CommandIssuer

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandManager.html b/docs/acf-core/co/aikar/commands/class-use/CommandManager.html index 383cad09..fc0fd2a0 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandManager.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandManager.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandManager (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandManager

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandOperationContext.html b/docs/acf-core/co/aikar/commands/class-use/CommandOperationContext.html index 6b644a0a..a2c6444b 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandOperationContext.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandOperationContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandOperationContext (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandOperationContext

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandParameter.html b/docs/acf-core/co/aikar/commands/class-use/CommandParameter.html index 093e30ca..727d54e1 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandParameter.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandParameter.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandParameter (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandParameter

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/CommandReplacements.html b/docs/acf-core/co/aikar/commands/class-use/CommandReplacements.html index 099fdcf9..5d12cdfc 100644 --- a/docs/acf-core/co/aikar/commands/class-use/CommandReplacements.html +++ b/docs/acf-core/co/aikar/commands/class-use/CommandReplacements.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.CommandReplacements (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.CommandReplacements

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/ConditionContext.html b/docs/acf-core/co/aikar/commands/class-use/ConditionContext.html index 2231bc90..ac0d61fc 100644 --- a/docs/acf-core/co/aikar/commands/class-use/ConditionContext.html +++ b/docs/acf-core/co/aikar/commands/class-use/ConditionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ConditionContext (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.ConditionContext

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/ConditionFailedException.html b/docs/acf-core/co/aikar/commands/class-use/ConditionFailedException.html index fe96a776..e29aaa44 100644 --- a/docs/acf-core/co/aikar/commands/class-use/ConditionFailedException.html +++ b/docs/acf-core/co/aikar/commands/class-use/ConditionFailedException.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ConditionFailedException (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.ConditionFailedException

                No usage of co.aikar.commands.ConditionFailedException
                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/ExceptionHandler.html b/docs/acf-core/co/aikar/commands/class-use/ExceptionHandler.html index 17a7a59c..81db8e43 100644 --- a/docs/acf-core/co/aikar/commands/class-use/ExceptionHandler.html +++ b/docs/acf-core/co/aikar/commands/class-use/ExceptionHandler.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.ExceptionHandler (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.ExceptionHandler

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/ForwardingCommand.html b/docs/acf-core/co/aikar/commands/class-use/ForwardingCommand.html index 2a22ffd5..12e09c0c 100644 --- a/docs/acf-core/co/aikar/commands/class-use/ForwardingCommand.html +++ b/docs/acf-core/co/aikar/commands/class-use/ForwardingCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ForwardingCommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.ForwardingCommand

                No usage of co.aikar.commands.ForwardingCommand
                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/HelpEntry.html b/docs/acf-core/co/aikar/commands/class-use/HelpEntry.html index 043038b8..141e448f 100644 --- a/docs/acf-core/co/aikar/commands/class-use/HelpEntry.html +++ b/docs/acf-core/co/aikar/commands/class-use/HelpEntry.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.HelpEntry (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.HelpEntry

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/InvalidCommandArgument.html b/docs/acf-core/co/aikar/commands/class-use/InvalidCommandArgument.html index 738d7f7b..2144cbf2 100644 --- a/docs/acf-core/co/aikar/commands/class-use/InvalidCommandArgument.html +++ b/docs/acf-core/co/aikar/commands/class-use/InvalidCommandArgument.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.InvalidCommandArgument (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.InvalidCommandArgument

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/InvalidCommandContextException.html b/docs/acf-core/co/aikar/commands/class-use/InvalidCommandContextException.html index 14ba7c59..09e76dcf 100644 --- a/docs/acf-core/co/aikar/commands/class-use/InvalidCommandContextException.html +++ b/docs/acf-core/co/aikar/commands/class-use/InvalidCommandContextException.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.InvalidCommandContextException (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.InvalidCommandContextException

                No usage of co.aikar.commands.InvalidCommandContextException
                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/IssuerLocaleChangedCallback.html b/docs/acf-core/co/aikar/commands/class-use/IssuerLocaleChangedCallback.html index b6982995..14ea7b4f 100644 --- a/docs/acf-core/co/aikar/commands/class-use/IssuerLocaleChangedCallback.html +++ b/docs/acf-core/co/aikar/commands/class-use/IssuerLocaleChangedCallback.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.IssuerLocaleChangedCallback (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.IssuerLocaleChangedCallback

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/Locales.html b/docs/acf-core/co/aikar/commands/class-use/Locales.html index 0babf1e4..724e5b4a 100644 --- a/docs/acf-core/co/aikar/commands/class-use/Locales.html +++ b/docs/acf-core/co/aikar/commands/class-use/Locales.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.Locales (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.Locales

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/MessageFormatter.html b/docs/acf-core/co/aikar/commands/class-use/MessageFormatter.html index e4c266cd..e51e860c 100644 --- a/docs/acf-core/co/aikar/commands/class-use/MessageFormatter.html +++ b/docs/acf-core/co/aikar/commands/class-use/MessageFormatter.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.MessageFormatter (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.MessageFormatter

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/MessageKeys.html b/docs/acf-core/co/aikar/commands/class-use/MessageKeys.html index e092afb1..c4400671 100644 --- a/docs/acf-core/co/aikar/commands/class-use/MessageKeys.html +++ b/docs/acf-core/co/aikar/commands/class-use/MessageKeys.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.MessageKeys (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.MessageKeys

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/MessageType.html b/docs/acf-core/co/aikar/commands/class-use/MessageType.html index c058763b..e5fbff3b 100644 --- a/docs/acf-core/co/aikar/commands/class-use/MessageType.html +++ b/docs/acf-core/co/aikar/commands/class-use/MessageType.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.MessageType (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.MessageType

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/RegisteredCommand.html b/docs/acf-core/co/aikar/commands/class-use/RegisteredCommand.html index 11088cf1..d9fc238b 100644 --- a/docs/acf-core/co/aikar/commands/class-use/RegisteredCommand.html +++ b/docs/acf-core/co/aikar/commands/class-use/RegisteredCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.RegisteredCommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.RegisteredCommand

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/RootCommand.html b/docs/acf-core/co/aikar/commands/class-use/RootCommand.html index f55202a7..8520a96b 100644 --- a/docs/acf-core/co/aikar/commands/class-use/RootCommand.html +++ b/docs/acf-core/co/aikar/commands/class-use/RootCommand.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.RootCommand (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.RootCommand

                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/ShowCommandHelp.html b/docs/acf-core/co/aikar/commands/class-use/ShowCommandHelp.html index 70957bb5..daabd038 100644 --- a/docs/acf-core/co/aikar/commands/class-use/ShowCommandHelp.html +++ b/docs/acf-core/co/aikar/commands/class-use/ShowCommandHelp.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ShowCommandHelp (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.ShowCommandHelp

                No usage of co.aikar.commands.ShowCommandHelp
                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/UnresolvedDependencyException.html b/docs/acf-core/co/aikar/commands/class-use/UnresolvedDependencyException.html index 4ecf16aa..3832c43f 100644 --- a/docs/acf-core/co/aikar/commands/class-use/UnresolvedDependencyException.html +++ b/docs/acf-core/co/aikar/commands/class-use/UnresolvedDependencyException.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.UnresolvedDependencyException (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.UnresolvedDependencyException

                No usage of co.aikar.commands.UnresolvedDependencyException
                +
                + diff --git a/docs/acf-core/co/aikar/commands/class-use/UnstableAPI.html b/docs/acf-core/co/aikar/commands/class-use/UnstableAPI.html index 86ed60da..0c5861ff 100644 --- a/docs/acf-core/co/aikar/commands/class-use/UnstableAPI.html +++ b/docs/acf-core/co/aikar/commands/class-use/UnstableAPI.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.UnstableAPI (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.UnstableAPI

                +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/ContextResolver.html b/docs/acf-core/co/aikar/commands/contexts/ContextResolver.html index 41d4fa18..5ffee881 100644 --- a/docs/acf-core/co/aikar/commands/contexts/ContextResolver.html +++ b/docs/acf-core/co/aikar/commands/contexts/ContextResolver.html @@ -1,12 +1,21 @@ - + - ContextResolver (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +
                -
                co.aikar.commands.contexts
                -

                Interface ContextResolver<T,C extends CommandExecutionContext<?,? extends CommandIssuer>>

                + +

                Interface ContextResolver<T,​C extends CommandExecutionContext<?,​? extends CommandIssuer>>

                @@ -105,17 +129,16 @@ var activeTableTab = "activeTableTab";
                All Known Subinterfaces:
                -
                IssuerAwareContextResolver<T,C>, IssuerOnlyContextResolver<T,C>, OptionalContextResolver<T,C>, SenderAwareContextResolver<T,C>
                +
                IssuerAwareContextResolver<T,​C>, IssuerOnlyContextResolver<T,​C>, OptionalContextResolver<T,​C>, SenderAwareContextResolver<T,​C>
                Functional Interface:
                This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

                -
                -
                @FunctionalInterface
                -public interface ContextResolver<T,C extends CommandExecutionContext<?,? extends CommandIssuer>>
                -
                This defines a context resolver, which parses T from C.
                +
                @FunctionalInterface
                +public interface ContextResolver<T,​C extends CommandExecutionContext<?,​? extends CommandIssuer>>
                +
                This defines a context resolver, which parses ContextResolver from ContextResolver.
                @@ -123,26 +146,30 @@ public interface
              • +
                +
              • @@ -150,49 +177,54 @@ public interface
              • +
                +
              • +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/IssuerAwareContextResolver.html b/docs/acf-core/co/aikar/commands/contexts/IssuerAwareContextResolver.html index cf4bb8d4..ee6cec2a 100644 --- a/docs/acf-core/co/aikar/commands/contexts/IssuerAwareContextResolver.html +++ b/docs/acf-core/co/aikar/commands/contexts/IssuerAwareContextResolver.html @@ -1,12 +1,21 @@ - + - IssuerAwareContextResolver (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +
                -
                co.aikar.commands.contexts
                -

                Interface IssuerAwareContextResolver<T,C extends CommandExecutionContext<?,? extends CommandIssuer>>

                + +

                Interface IssuerAwareContextResolver<T,​C extends CommandExecutionContext<?,​? extends CommandIssuer>>

                @@ -94,16 +118,15 @@
              • All Superinterfaces:
                -
                ContextResolver<T,C>
                +
                ContextResolver<T,​C>
                All Known Subinterfaces:
                -
                SenderAwareContextResolver<T,C>
                +
                SenderAwareContextResolver<T,​C>

                -
                -
                public interface IssuerAwareContextResolver<T,C extends CommandExecutionContext<?,? extends CommandIssuer>>
                -extends ContextResolver<T,C>
                +
                public interface IssuerAwareContextResolver<T,​C extends CommandExecutionContext<?,​? extends CommandIssuer>>
                +extends ContextResolver<T,​C>
              • @@ -111,35 +134,40 @@ extends
              • +
                +
              • +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/IssuerOnlyContextResolver.html b/docs/acf-core/co/aikar/commands/contexts/IssuerOnlyContextResolver.html index 079d2559..1b4e17c1 100644 --- a/docs/acf-core/co/aikar/commands/contexts/IssuerOnlyContextResolver.html +++ b/docs/acf-core/co/aikar/commands/contexts/IssuerOnlyContextResolver.html @@ -1,12 +1,21 @@ - + - IssuerOnlyContextResolver (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +
                -
                co.aikar.commands.contexts
                -

                Interface IssuerOnlyContextResolver<T,C extends CommandExecutionContext<?,? extends CommandIssuer>>

                + +

                Interface IssuerOnlyContextResolver<T,​C extends CommandExecutionContext<?,​? extends CommandIssuer>>

                @@ -99,12 +123,11 @@
                All Superinterfaces:
                -
                ContextResolver<T,C>
                +
                ContextResolver<T,​C>

                -
                -
                public interface IssuerOnlyContextResolver<T,C extends CommandExecutionContext<?,? extends CommandIssuer>>
                -extends ContextResolver<T,C>
                +
                public interface IssuerOnlyContextResolver<T,​C extends CommandExecutionContext<?,​? extends CommandIssuer>>
                +extends ContextResolver<T,​C>
                A context resolver that will never consume input, and only resolves using the context of the issuer of the command
                @@ -113,35 +136,40 @@ extends
              • +
                +
              • +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/OptionalContextResolver.html b/docs/acf-core/co/aikar/commands/contexts/OptionalContextResolver.html index 8110d36c..8f50119e 100644 --- a/docs/acf-core/co/aikar/commands/contexts/OptionalContextResolver.html +++ b/docs/acf-core/co/aikar/commands/contexts/OptionalContextResolver.html @@ -1,12 +1,21 @@ - + - OptionalContextResolver (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +
                -
                co.aikar.commands.contexts
                -

                Interface OptionalContextResolver<T,C extends CommandExecutionContext<?,? extends CommandIssuer>>

                + +

                Interface OptionalContextResolver<T,​C extends CommandExecutionContext<?,​? extends CommandIssuer>>

                @@ -99,13 +123,12 @@
                All Superinterfaces:
                -
                ContextResolver<T,C>
                +
                ContextResolver<T,​C>

                -
                -
                public interface OptionalContextResolver<T,C extends CommandExecutionContext<?,? extends CommandIssuer>>
                -extends ContextResolver<T,C>
                -
                The same as ContextResolver, however it can accept a null context. +
                public interface OptionalContextResolver<T,​C extends CommandExecutionContext<?,​? extends CommandIssuer>>
                +extends ContextResolver<T,​C>
                +
                The same as ContextResolver, however it can accept a null context. If the parameter was marked optional, will still be called with an empty args list
                @@ -115,35 +138,40 @@ extends
              • +
                +
              • +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/SenderAwareContextResolver.html b/docs/acf-core/co/aikar/commands/contexts/SenderAwareContextResolver.html index b9ae7c38..97896d89 100644 --- a/docs/acf-core/co/aikar/commands/contexts/SenderAwareContextResolver.html +++ b/docs/acf-core/co/aikar/commands/contexts/SenderAwareContextResolver.html @@ -1,12 +1,21 @@ - + - SenderAwareContextResolver (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +
                -
                co.aikar.commands.contexts
                -

                Interface SenderAwareContextResolver<T,C extends CommandExecutionContext<?,? extends CommandIssuer>>

                + +

                Interface SenderAwareContextResolver<T,​C extends CommandExecutionContext<?,​? extends CommandIssuer>>

                @@ -94,20 +118,19 @@
              • All Superinterfaces:
                -
                ContextResolver<T,C>, IssuerAwareContextResolver<T,C>
                +
                ContextResolver<T,​C>, IssuerAwareContextResolver<T,​C>

                -
                Deprecated.  - +
                @Deprecated
                +public interface SenderAwareContextResolver<T,​C extends CommandExecutionContext<?,​? extends CommandIssuer>>
                +extends IssuerAwareContextResolver<T,​C>
                +
                Deprecated. +
                -
                -
                @Deprecated
                -public interface SenderAwareContextResolver<T,C extends CommandExecutionContext<?,? extends CommandIssuer>>
                -extends IssuerAwareContextResolver<T,C>
                Wrapper for IssuerAwareContextResolver
                See Also:
                -
                IssuerAwareContextResolver
                +
                IssuerAwareContextResolver
              • @@ -116,35 +139,40 @@ extends
              • +
                +
              • +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/class-use/ContextResolver.html b/docs/acf-core/co/aikar/commands/contexts/class-use/ContextResolver.html index 2c2792fa..06470a42 100644 --- a/docs/acf-core/co/aikar/commands/contexts/class-use/ContextResolver.html +++ b/docs/acf-core/co/aikar/commands/contexts/class-use/ContextResolver.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.contexts.ContextResolver (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.contexts.ContextResolver

                +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/class-use/IssuerAwareContextResolver.html b/docs/acf-core/co/aikar/commands/contexts/class-use/IssuerAwareContextResolver.html index 1efaa8a3..112d2f16 100644 --- a/docs/acf-core/co/aikar/commands/contexts/class-use/IssuerAwareContextResolver.html +++ b/docs/acf-core/co/aikar/commands/contexts/class-use/IssuerAwareContextResolver.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.contexts.IssuerAwareContextResolver (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.contexts.IssuerAwareContextResolver

                +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/class-use/IssuerOnlyContextResolver.html b/docs/acf-core/co/aikar/commands/contexts/class-use/IssuerOnlyContextResolver.html index 1c0c85c0..081e3e53 100644 --- a/docs/acf-core/co/aikar/commands/contexts/class-use/IssuerOnlyContextResolver.html +++ b/docs/acf-core/co/aikar/commands/contexts/class-use/IssuerOnlyContextResolver.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.contexts.IssuerOnlyContextResolver (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.contexts.IssuerOnlyContextResolver

                +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/class-use/OptionalContextResolver.html b/docs/acf-core/co/aikar/commands/contexts/class-use/OptionalContextResolver.html index b68a83d0..aa0cdc0f 100644 --- a/docs/acf-core/co/aikar/commands/contexts/class-use/OptionalContextResolver.html +++ b/docs/acf-core/co/aikar/commands/contexts/class-use/OptionalContextResolver.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.contexts.OptionalContextResolver (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.contexts.OptionalContextResolver

                +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/class-use/SenderAwareContextResolver.html b/docs/acf-core/co/aikar/commands/contexts/class-use/SenderAwareContextResolver.html index c6b142c7..5008a732 100644 --- a/docs/acf-core/co/aikar/commands/contexts/class-use/SenderAwareContextResolver.html +++ b/docs/acf-core/co/aikar/commands/contexts/class-use/SenderAwareContextResolver.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.contexts.SenderAwareContextResolver (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Interface
                co.aikar.commands.contexts.SenderAwareContextResolver

                No usage of co.aikar.commands.contexts.SenderAwareContextResolver
                +
                + diff --git a/docs/acf-core/co/aikar/commands/contexts/package-summary.html b/docs/acf-core/co/aikar/commands/contexts/package-summary.html index 639ac656..e7deeba0 100644 --- a/docs/acf-core/co/aikar/commands/contexts/package-summary.html +++ b/docs/acf-core/co/aikar/commands/contexts/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.contexts (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Package co.aikar.commands.contexts

                +
                + diff --git a/docs/acf-core/co/aikar/commands/package-summary.html b/docs/acf-core/co/aikar/commands/package-summary.html index 6e124d90..0cc8f5b6 100644 --- a/docs/acf-core/co/aikar/commands/package-summary.html +++ b/docs/acf-core/co/aikar/commands/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Package co.aikar.commands

                +
                + diff --git a/docs/acf-core/co/aikar/commands/package-tree.html b/docs/acf-core/co/aikar/commands/package-tree.html index 196d342f..393c3fd0 100644 --- a/docs/acf-core/co/aikar/commands/package-tree.html +++ b/docs/acf-core/co/aikar/commands/package-tree.html @@ -1,12 +1,21 @@ - + - co.aikar.commands Class Hierarchy (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Hierarchy For Package co.aikar.commands

                Package Hierarchies: @@ -76,48 +100,49 @@
                +

                Class Hierarchy

                +

                Interface Hierarchy

                +
                +

                Annotation Type Hierarchy

                +
                +

                Enum Hierarchy

                +
                +
                + diff --git a/docs/acf-core/co/aikar/commands/package-use.html b/docs/acf-core/co/aikar/commands/package-use.html index 1102f318..ccecf27e 100644 --- a/docs/acf-core/co/aikar/commands/package-use.html +++ b/docs/acf-core/co/aikar/commands/package-use.html @@ -1,12 +1,21 @@ - + - Uses of Package co.aikar.commands (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Package
                co.aikar.commands

                + +
                +
                @@ -191,75 +223,82 @@ implements
              • +
                +
                +
                +
              • +
                + diff --git a/docs/acf-core/co/aikar/commands/processors/class-use/ConditionsProcessor.html b/docs/acf-core/co/aikar/commands/processors/class-use/ConditionsProcessor.html index e3a99593..5a74b3ed 100644 --- a/docs/acf-core/co/aikar/commands/processors/class-use/ConditionsProcessor.html +++ b/docs/acf-core/co/aikar/commands/processors/class-use/ConditionsProcessor.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.processors.ConditionsProcessor (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.processors.ConditionsProcessor

                No usage of co.aikar.commands.processors.ConditionsProcessor
                +
                + diff --git a/docs/acf-core/co/aikar/commands/processors/package-summary.html b/docs/acf-core/co/aikar/commands/processors/package-summary.html index 3b44266c..971cb4b7 100644 --- a/docs/acf-core/co/aikar/commands/processors/package-summary.html +++ b/docs/acf-core/co/aikar/commands/processors/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.processors (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Package co.aikar.commands.processors

                +
                + diff --git a/docs/acf-core/co/aikar/commands/processors/package-tree.html b/docs/acf-core/co/aikar/commands/processors/package-tree.html index f91a2302..6ffd7a86 100644 --- a/docs/acf-core/co/aikar/commands/processors/package-tree.html +++ b/docs/acf-core/co/aikar/commands/processors/package-tree.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.processors Class Hierarchy (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Hierarchy For Package co.aikar.commands.processors

                Package Hierarchies: @@ -76,25 +100,30 @@
                +

                Class Hierarchy

                +
                +
                + diff --git a/docs/acf-core/co/aikar/commands/processors/package-use.html b/docs/acf-core/co/aikar/commands/processors/package-use.html index 43411ad4..dde9050c 100644 --- a/docs/acf-core/co/aikar/commands/processors/package-use.html +++ b/docs/acf-core/co/aikar/commands/processors/package-use.html @@ -1,12 +1,21 @@ - + - Uses of Package co.aikar.commands.processors (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Package
                co.aikar.commands.processors

                No usage of co.aikar.commands.processors
                +
                + diff --git a/docs/acf-core/constant-values.html b/docs/acf-core/constant-values.html index f083aa10..4b71373a 100644 --- a/docs/acf-core/constant-values.html +++ b/docs/acf-core/constant-values.html @@ -1,12 +1,21 @@ - + - Constant Field Values (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Constant Field Values

                +

                Contents

                +
                -
                +
                +

                co.aikar.*

                +
                +
                + diff --git a/docs/acf-core/deprecated-list.html b/docs/acf-core/deprecated-list.html index 386a7bdf..00d77688 100644 --- a/docs/acf-core/deprecated-list.html +++ b/docs/acf-core/deprecated-list.html @@ -1,12 +1,21 @@ - + - Deprecated List (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +
                -
                +
                - + - + - + - +
                +
                +
                + +

                Copyright © 2020. All rights reserved.

                +
                + diff --git a/docs/acf-core/jquery/external/jquery/jquery.js b/docs/acf-core/jquery/external/jquery/jquery.js new file mode 100644 index 00000000..9b5206bc --- /dev/null +++ b/docs/acf-core/jquery/external/jquery/jquery.js @@ -0,0 +1,10364 @@ +/*! + * jQuery JavaScript Library v3.3.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2018-01-20T17:24Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + + + + var preservedScriptAttributes = { + type: true, + src: true, + noModule: true + }; + + function DOMEval( code, doc, node ) { + doc = doc || document; + + var i, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + if ( node[ i ] ) { + script[ i ] = node[ i ]; + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.3.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && Array.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( nodeName( elem, "iframe" ) ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting
                ", "
                " ], + col: [ 2, "", "
                " ], + tr: [ 2, "", "
                " ], + td: [ 3, "", "
                " ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + div.style.position = "absolute"; + scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a property mapped along what jQuery.cssProps suggests or to +// a vendor prefixed property. +function finalPropName( name ) { + var ret = jQuery.cssProps[ name ]; + if ( !ret ) { + ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + } + return ret; +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + ) ); + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + val = curCSS( elem, dimension, styles ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox; + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = valueIsBorderBox && + ( support.boxSizingReliable() || val === elem.style[ dimension ] ); + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + if ( val === "auto" || + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { + + val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; + + // offsetWidth/offsetHeight provide border-box values + valueIsBorderBox = true; + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra && boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ); + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && support.scrollboxSize() === styles.position ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = Date.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "\r\n"; + +// inject VBScript +document.write(IEBinaryToArray_ByteStr_Script); + +global.JSZipUtils._getBinaryFromXHR = function (xhr) { + var binary = xhr.responseBody; + var byteMapping = {}; + for ( var i = 0; i < 256; i++ ) { + for ( var j = 0; j < 256; j++ ) { + byteMapping[ String.fromCharCode( i + (j << 8) ) ] = + String.fromCharCode(i) + String.fromCharCode(j); + } + } + var rawBytes = IEBinaryToArray_ByteStr(binary); + var lastChr = IEBinaryToArray_ByteStr_Last(binary); + return rawBytes.replace(/[\s\S]/g, function( match ) { + return byteMapping[match]; + }) + lastChr; +}; + +// enforcing Stuk's coding style +// vim: set shiftwidth=4 softtabstop=4: + +},{}]},{},[1]) +; diff --git a/docs/acf-core/jquery/jszip-utils/dist/jszip-utils-ie.min.js b/docs/acf-core/jquery/jszip-utils/dist/jszip-utils-ie.min.js new file mode 100644 index 00000000..93d8bc8e --- /dev/null +++ b/docs/acf-core/jquery/jszip-utils/dist/jszip-utils-ie.min.js @@ -0,0 +1,10 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); diff --git a/docs/acf-core/jquery/jszip-utils/dist/jszip-utils.js b/docs/acf-core/jquery/jszip-utils/dist/jszip-utils.js new file mode 100644 index 00000000..775895ec --- /dev/null +++ b/docs/acf-core/jquery/jszip-utils/dist/jszip-utils.js @@ -0,0 +1,118 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ + +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64; + enc4 = remainingBytes > 2 ? (chr3 & 63) : 64; + + output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4)); + + } + + return output.join(""); +}; + +// public method for decoding +exports.decode = function(input) { + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0, resultIndex = 0; + + var dataUrlPrefix = "data:"; + + if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) { + // This is a common error: people give a data url + // (data:image/png;base64,iVBOR...) with a {base64: true} and + // wonders why things don't work. + // We can detect that the string input looks like a data url but we + // *can't* be sure it is one: removing everything up to the comma would + // be too dangerous. + throw new Error("Invalid base64 input, it looks like a data url."); + } + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + var totalLength = input.length * 3 / 4; + if(input.charAt(input.length - 1) === _keyStr.charAt(64)) { + totalLength--; + } + if(input.charAt(input.length - 2) === _keyStr.charAt(64)) { + totalLength--; + } + if (totalLength % 1 !== 0) { + // totalLength is not an integer, the length does not match a valid + // base64 content. That can happen if: + // - the input is not a base64 content + // - the input is *almost* a base64 content, with a extra chars at the + // beginning or at the end + // - the input uses a base64 variant (base64url for example) + throw new Error("Invalid base64 input, bad content length."); + } + var output; + if (support.uint8array) { + output = new Uint8Array(totalLength|0); + } else { + output = new Array(totalLength|0); + } + + while (i < input.length) { + + enc1 = _keyStr.indexOf(input.charAt(i++)); + enc2 = _keyStr.indexOf(input.charAt(i++)); + enc3 = _keyStr.indexOf(input.charAt(i++)); + enc4 = _keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output[resultIndex++] = chr1; + + if (enc3 !== 64) { + output[resultIndex++] = chr2; + } + if (enc4 !== 64) { + output[resultIndex++] = chr3; + } + + } + + return output; +}; + +},{"./support":30,"./utils":32}],2:[function(require,module,exports){ +'use strict'; + +var external = require("./external"); +var DataWorker = require('./stream/DataWorker'); +var DataLengthProbe = require('./stream/DataLengthProbe'); +var Crc32Probe = require('./stream/Crc32Probe'); +var DataLengthProbe = require('./stream/DataLengthProbe'); + +/** + * Represent a compressed object, with everything needed to decompress it. + * @constructor + * @param {number} compressedSize the size of the data compressed. + * @param {number} uncompressedSize the size of the data after decompression. + * @param {number} crc32 the crc32 of the decompressed file. + * @param {object} compression the type of compression, see lib/compressions.js. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data. + */ +function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) { + this.compressedSize = compressedSize; + this.uncompressedSize = uncompressedSize; + this.crc32 = crc32; + this.compression = compression; + this.compressedContent = data; +} + +CompressedObject.prototype = { + /** + * Create a worker to get the uncompressed content. + * @return {GenericWorker} the worker. + */ + getContentWorker : function () { + var worker = new DataWorker(external.Promise.resolve(this.compressedContent)) + .pipe(this.compression.uncompressWorker()) + .pipe(new DataLengthProbe("data_length")); + + var that = this; + worker.on("end", function () { + if(this.streamInfo['data_length'] !== that.uncompressedSize) { + throw new Error("Bug : uncompressed data size mismatch"); + } + }); + return worker; + }, + /** + * Create a worker to get the compressed content. + * @return {GenericWorker} the worker. + */ + getCompressedWorker : function () { + return new DataWorker(external.Promise.resolve(this.compressedContent)) + .withStreamInfo("compressedSize", this.compressedSize) + .withStreamInfo("uncompressedSize", this.uncompressedSize) + .withStreamInfo("crc32", this.crc32) + .withStreamInfo("compression", this.compression) + ; + } +}; + +/** + * Chain the given worker with other workers to compress the content with the + * given compresion. + * @param {GenericWorker} uncompressedWorker the worker to pipe. + * @param {Object} compression the compression object. + * @param {Object} compressionOptions the options to use when compressing. + * @return {GenericWorker} the new worker compressing the content. + */ +CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions) { + return uncompressedWorker + .pipe(new Crc32Probe()) + .pipe(new DataLengthProbe("uncompressedSize")) + .pipe(compression.compressWorker(compressionOptions)) + .pipe(new DataLengthProbe("compressedSize")) + .withStreamInfo("compression", compression); +}; + +module.exports = CompressedObject; + +},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require("./stream/GenericWorker"); + +exports.STORE = { + magic: "\x00\x00", + compressWorker : function (compressionOptions) { + return new GenericWorker("STORE compression"); + }, + uncompressWorker : function () { + return new GenericWorker("STORE decompression"); + } +}; +exports.DEFLATE = require('./flate'); + +},{"./flate":7,"./stream/GenericWorker":28}],4:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); + +/** + * The following functions come from pako, from pako/lib/zlib/crc32.js + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +// That's all for the pako functions. + +/** + * Compute the crc32 of a string. + * This is almost the same as the function crc32, but for strings. Using the + * same function for the two use cases leads to horrible performances. + * @param {Number} crc the starting value of the crc. + * @param {String} str the string to use. + * @param {Number} len the length of the string. + * @param {Number} pos the starting position for the crc32 computation. + * @return {Number} the computed crc32. + */ +function crc32str(crc, str, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +module.exports = function crc32wrapper(input, crc) { + if (typeof input === "undefined" || !input.length) { + return 0; + } + + var isArray = utils.getTypeOf(input) !== "string"; + + if(isArray) { + return crc32(crc|0, input, input.length, 0); + } else { + return crc32str(crc|0, input, input.length, 0); + } +}; + +},{"./utils":32}],5:[function(require,module,exports){ +'use strict'; +exports.base64 = false; +exports.binary = false; +exports.dir = false; +exports.createFolders = true; +exports.date = null; +exports.compression = null; +exports.compressionOptions = null; +exports.comment = null; +exports.unixPermissions = null; +exports.dosPermissions = null; + +},{}],6:[function(require,module,exports){ +/* global Promise */ +'use strict'; + +// load the global object first: +// - it should be better integrated in the system (unhandledRejection in node) +// - the environment may have a custom Promise implementation (see zone.js) +var ES6Promise = null; +if (typeof Promise !== "undefined") { + ES6Promise = Promise; +} else { + ES6Promise = require("lie"); +} + +/** + * Let the user use/change some implementations. + */ +module.exports = { + Promise: ES6Promise +}; + +},{"lie":58}],7:[function(require,module,exports){ +'use strict'; +var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); + +var pako = require("pako"); +var utils = require("./utils"); +var GenericWorker = require("./stream/GenericWorker"); + +var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array"; + +exports.magic = "\x08\x00"; + +/** + * Create a worker that uses pako to inflate/deflate. + * @constructor + * @param {String} action the name of the pako function to call : either "Deflate" or "Inflate". + * @param {Object} options the options to use when (de)compressing. + */ +function FlateWorker(action, options) { + GenericWorker.call(this, "FlateWorker/" + action); + + this._pako = null; + this._pakoAction = action; + this._pakoOptions = options; + // the `meta` object from the last chunk received + // this allow this worker to pass around metadata + this.meta = {}; +} + +utils.inherits(FlateWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +FlateWorker.prototype.processChunk = function (chunk) { + this.meta = chunk.meta; + if (this._pako === null) { + this._createPako(); + } + this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false); +}; + +/** + * @see GenericWorker.flush + */ +FlateWorker.prototype.flush = function () { + GenericWorker.prototype.flush.call(this); + if (this._pako === null) { + this._createPako(); + } + this._pako.push([], true); +}; +/** + * @see GenericWorker.cleanUp + */ +FlateWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this._pako = null; +}; + +/** + * Create the _pako object. + * TODO: lazy-loading this object isn't the best solution but it's the + * quickest. The best solution is to lazy-load the worker list. See also the + * issue #446. + */ +FlateWorker.prototype._createPako = function () { + this._pako = new pako[this._pakoAction]({ + raw: true, + level: this._pakoOptions.level || -1 // default compression + }); + var self = this; + this._pako.onData = function(data) { + self.push({ + data : data, + meta : self.meta + }); + }; +}; + +exports.compressWorker = function (compressionOptions) { + return new FlateWorker("Deflate", compressionOptions); +}; +exports.uncompressWorker = function () { + return new FlateWorker("Inflate", {}); +}; + +},{"./stream/GenericWorker":28,"./utils":32,"pako":59}],8:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); +var utf8 = require('../utf8'); +var crc32 = require('../crc32'); +var signature = require('../signature'); + +/** + * Transform an integer into a string in hexadecimal. + * @private + * @param {number} dec the number to convert. + * @param {number} bytes the number of bytes to generate. + * @returns {string} the result. + */ +var decToHex = function(dec, bytes) { + var hex = "", i; + for (i = 0; i < bytes; i++) { + hex += String.fromCharCode(dec & 0xff); + dec = dec >>> 8; + } + return hex; +}; + +/** + * Generate the UNIX part of the external file attributes. + * @param {Object} unixPermissions the unix permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : + * + * TTTTsstrwxrwxrwx0000000000ADVSHR + * ^^^^____________________________ file type, see zipinfo.c (UNX_*) + * ^^^_________________________ setuid, setgid, sticky + * ^^^^^^^^^________________ permissions + * ^^^^^^^^^^______ not used ? + * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only + */ +var generateUnixExternalFileAttr = function (unixPermissions, isDir) { + + var result = unixPermissions; + if (!unixPermissions) { + // I can't use octal values in strict mode, hence the hexa. + // 040775 => 0x41fd + // 0100664 => 0x81b4 + result = isDir ? 0x41fd : 0x81b4; + } + return (result & 0xFFFF) << 16; +}; + +/** + * Generate the DOS part of the external file attributes. + * @param {Object} dosPermissions the dos permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * Bit 0 Read-Only + * Bit 1 Hidden + * Bit 2 System + * Bit 3 Volume Label + * Bit 4 Directory + * Bit 5 Archive + */ +var generateDosExternalFileAttr = function (dosPermissions, isDir) { + + // the dir flag is already set for compatibility + return (dosPermissions || 0) & 0x3F; +}; + +/** + * Generate the various parts used in the construction of the final zip file. + * @param {Object} streamInfo the hash with informations about the compressed file. + * @param {Boolean} streamedContent is the content streamed ? + * @param {Boolean} streamingEnded is the stream finished ? + * @param {number} offset the current offset from the start of the zip file. + * @param {String} platform let's pretend we are this platform (change platform dependents fields) + * @param {Function} encodeFileName the function to encode the file name / comment. + * @return {Object} the zip parts. + */ +var generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) { + var file = streamInfo['file'], + compression = streamInfo['compression'], + useCustomEncoding = encodeFileName !== utf8.utf8encode, + encodedFileName = utils.transformTo("string", encodeFileName(file.name)), + utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), + comment = file.comment, + encodedComment = utils.transformTo("string", encodeFileName(comment)), + utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), + useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, + useUTF8ForComment = utfEncodedComment.length !== comment.length, + dosTime, + dosDate, + extraFields = "", + unicodePathExtraField = "", + unicodeCommentExtraField = "", + dir = file.dir, + date = file.date; + + + var dataInfo = { + crc32 : 0, + compressedSize : 0, + uncompressedSize : 0 + }; + + // if the content is streamed, the sizes/crc32 are only available AFTER + // the end of the stream. + if (!streamedContent || streamingEnded) { + dataInfo.crc32 = streamInfo['crc32']; + dataInfo.compressedSize = streamInfo['compressedSize']; + dataInfo.uncompressedSize = streamInfo['uncompressedSize']; + } + + var bitflag = 0; + if (streamedContent) { + // Bit 3: the sizes/crc32 are set to zero in the local header. + // The correct values are put in the data descriptor immediately + // following the compressed data. + bitflag |= 0x0008; + } + if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) { + // Bit 11: Language encoding flag (EFS). + bitflag |= 0x0800; + } + + + var extFileAttr = 0; + var versionMadeBy = 0; + if (dir) { + // dos or unix, we set the dos dir flag + extFileAttr |= 0x00010; + } + if(platform === "UNIX") { + versionMadeBy = 0x031E; // UNIX, version 3.0 + extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); + } else { // DOS or other, fallback to DOS + versionMadeBy = 0x0014; // DOS, version 2.0 + extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); + } + + // date + // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html + + dosTime = date.getUTCHours(); + dosTime = dosTime << 6; + dosTime = dosTime | date.getUTCMinutes(); + dosTime = dosTime << 5; + dosTime = dosTime | date.getUTCSeconds() / 2; + + dosDate = date.getUTCFullYear() - 1980; + dosDate = dosDate << 4; + dosDate = dosDate | (date.getUTCMonth() + 1); + dosDate = dosDate << 5; + dosDate = dosDate | date.getUTCDate(); + + if (useUTF8ForFileName) { + // set the unicode path extra field. unzip needs at least one extra + // field to correctly handle unicode path, so using the path is as good + // as any other information. This could improve the situation with + // other archive managers too. + // This field is usually used without the utf8 flag, with a non + // unicode path in the header (winrar, winzip). This helps (a bit) + // with the messy Windows' default compressed folders feature but + // breaks on p7zip which doesn't seek the unicode path extra field. + // So for now, UTF-8 everywhere ! + unicodePathExtraField = + // Version + decToHex(1, 1) + + // NameCRC32 + decToHex(crc32(encodedFileName), 4) + + // UnicodeName + utfEncodedFileName; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x70" + + // size + decToHex(unicodePathExtraField.length, 2) + + // content + unicodePathExtraField; + } + + if(useUTF8ForComment) { + + unicodeCommentExtraField = + // Version + decToHex(1, 1) + + // CommentCRC32 + decToHex(crc32(encodedComment), 4) + + // UnicodeName + utfEncodedComment; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x63" + + // size + decToHex(unicodeCommentExtraField.length, 2) + + // content + unicodeCommentExtraField; + } + + var header = ""; + + // version needed to extract + header += "\x0A\x00"; + // general purpose bit flag + header += decToHex(bitflag, 2); + // compression method + header += compression.magic; + // last mod file time + header += decToHex(dosTime, 2); + // last mod file date + header += decToHex(dosDate, 2); + // crc-32 + header += decToHex(dataInfo.crc32, 4); + // compressed size + header += decToHex(dataInfo.compressedSize, 4); + // uncompressed size + header += decToHex(dataInfo.uncompressedSize, 4); + // file name length + header += decToHex(encodedFileName.length, 2); + // extra field length + header += decToHex(extraFields.length, 2); + + + var fileRecord = signature.LOCAL_FILE_HEADER + header + encodedFileName + extraFields; + + var dirRecord = signature.CENTRAL_FILE_HEADER + + // version made by (00: DOS) + decToHex(versionMadeBy, 2) + + // file header (common to file and central directory) + header + + // file comment length + decToHex(encodedComment.length, 2) + + // disk number start + "\x00\x00" + + // internal file attributes TODO + "\x00\x00" + + // external file attributes + decToHex(extFileAttr, 4) + + // relative offset of local header + decToHex(offset, 4) + + // file name + encodedFileName + + // extra field + extraFields + + // file comment + encodedComment; + + return { + fileRecord: fileRecord, + dirRecord: dirRecord + }; +}; + +/** + * Generate the EOCD record. + * @param {Number} entriesCount the number of entries in the zip file. + * @param {Number} centralDirLength the length (in bytes) of the central dir. + * @param {Number} localDirLength the length (in bytes) of the local dir. + * @param {String} comment the zip file comment as a binary string. + * @param {Function} encodeFileName the function to encode the comment. + * @return {String} the EOCD record. + */ +var generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) { + var dirEnd = ""; + var encodedComment = utils.transformTo("string", encodeFileName(comment)); + + // end of central dir signature + dirEnd = signature.CENTRAL_DIRECTORY_END + + // number of this disk + "\x00\x00" + + // number of the disk with the start of the central directory + "\x00\x00" + + // total number of entries in the central directory on this disk + decToHex(entriesCount, 2) + + // total number of entries in the central directory + decToHex(entriesCount, 2) + + // size of the central directory 4 bytes + decToHex(centralDirLength, 4) + + // offset of start of central directory with respect to the starting disk number + decToHex(localDirLength, 4) + + // .ZIP file comment length + decToHex(encodedComment.length, 2) + + // .ZIP file comment + encodedComment; + + return dirEnd; +}; + +/** + * Generate data descriptors for a file entry. + * @param {Object} streamInfo the hash generated by a worker, containing informations + * on the file entry. + * @return {String} the data descriptors. + */ +var generateDataDescriptors = function (streamInfo) { + var descriptor = ""; + descriptor = signature.DATA_DESCRIPTOR + + // crc-32 4 bytes + decToHex(streamInfo['crc32'], 4) + + // compressed size 4 bytes + decToHex(streamInfo['compressedSize'], 4) + + // uncompressed size 4 bytes + decToHex(streamInfo['uncompressedSize'], 4); + + return descriptor; +}; + + +/** + * A worker to concatenate other workers to create a zip file. + * @param {Boolean} streamFiles `true` to stream the content of the files, + * `false` to accumulate it. + * @param {String} comment the comment to use. + * @param {String} platform the platform to use, "UNIX" or "DOS". + * @param {Function} encodeFileName the function to encode file names and comments. + */ +function ZipFileWorker(streamFiles, comment, platform, encodeFileName) { + GenericWorker.call(this, "ZipFileWorker"); + // The number of bytes written so far. This doesn't count accumulated chunks. + this.bytesWritten = 0; + // The comment of the zip file + this.zipComment = comment; + // The platform "generating" the zip file. + this.zipPlatform = platform; + // the function to encode file names and comments. + this.encodeFileName = encodeFileName; + // Should we stream the content of the files ? + this.streamFiles = streamFiles; + // If `streamFiles` is false, we will need to accumulate the content of the + // files to calculate sizes / crc32 (and write them *before* the content). + // This boolean indicates if we are accumulating chunks (it will change a lot + // during the lifetime of this worker). + this.accumulate = false; + // The buffer receiving chunks when accumulating content. + this.contentBuffer = []; + // The list of generated directory records. + this.dirRecords = []; + // The offset (in bytes) from the beginning of the zip file for the current source. + this.currentSourceOffset = 0; + // The total number of entries in this zip file. + this.entriesCount = 0; + // the name of the file currently being added, null when handling the end of the zip file. + // Used for the emited metadata. + this.currentFile = null; + + + + this._sources = []; +} +utils.inherits(ZipFileWorker, GenericWorker); + +/** + * @see GenericWorker.push + */ +ZipFileWorker.prototype.push = function (chunk) { + + var currentFilePercent = chunk.meta.percent || 0; + var entriesCount = this.entriesCount; + var remainingFiles = this._sources.length; + + if(this.accumulate) { + this.contentBuffer.push(chunk); + } else { + this.bytesWritten += chunk.data.length; + + GenericWorker.prototype.push.call(this, { + data : chunk.data, + meta : { + currentFile : this.currentFile, + percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100 + } + }); + } +}; + +/** + * The worker started a new source (an other worker). + * @param {Object} streamInfo the streamInfo object from the new source. + */ +ZipFileWorker.prototype.openedSource = function (streamInfo) { + this.currentSourceOffset = this.bytesWritten; + this.currentFile = streamInfo['file'].name; + + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + + // don't stream folders (because they don't have any content) + if(streamedContent) { + var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + } else { + // we need to wait for the whole file before pushing anything + this.accumulate = true; + } +}; + +/** + * The worker finished a source (an other worker). + * @param {Object} streamInfo the streamInfo object from the finished source. + */ +ZipFileWorker.prototype.closedSource = function (streamInfo) { + this.accumulate = false; + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + + this.dirRecords.push(record.dirRecord); + if(streamedContent) { + // after the streamed file, we put data descriptors + this.push({ + data : generateDataDescriptors(streamInfo), + meta : {percent:100} + }); + } else { + // the content wasn't streamed, we need to push everything now + // first the file record, then the content + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + while(this.contentBuffer.length) { + this.push(this.contentBuffer.shift()); + } + } + this.currentFile = null; +}; + +/** + * @see GenericWorker.flush + */ +ZipFileWorker.prototype.flush = function () { + + var localDirLength = this.bytesWritten; + for(var i = 0; i < this.dirRecords.length; i++) { + this.push({ + data : this.dirRecords[i], + meta : {percent:100} + }); + } + var centralDirLength = this.bytesWritten - localDirLength; + + var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName); + + this.push({ + data : dirEnd, + meta : {percent:100} + }); +}; + +/** + * Prepare the next source to be read. + */ +ZipFileWorker.prototype.prepareNextSource = function () { + this.previous = this._sources.shift(); + this.openedSource(this.previous.streamInfo); + if (this.isPaused) { + this.previous.pause(); + } else { + this.previous.resume(); + } +}; + +/** + * @see GenericWorker.registerPrevious + */ +ZipFileWorker.prototype.registerPrevious = function (previous) { + this._sources.push(previous); + var self = this; + + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.closedSource(self.previous.streamInfo); + if(self._sources.length) { + self.prepareNextSource(); + } else { + self.end(); + } + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; +}; + +/** + * @see GenericWorker.resume + */ +ZipFileWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this.previous && this._sources.length) { + this.prepareNextSource(); + return true; + } + if (!this.previous && !this._sources.length && !this.generatedError) { + this.end(); + return true; + } +}; + +/** + * @see GenericWorker.error + */ +ZipFileWorker.prototype.error = function (e) { + var sources = this._sources; + if(!GenericWorker.prototype.error.call(this, e)) { + return false; + } + for(var i = 0; i < sources.length; i++) { + try { + sources[i].error(e); + } catch(e) { + // the `error` exploded, nothing to do + } + } + return true; +}; + +/** + * @see GenericWorker.lock + */ +ZipFileWorker.prototype.lock = function () { + GenericWorker.prototype.lock.call(this); + var sources = this._sources; + for(var i = 0; i < sources.length; i++) { + sources[i].lock(); + } +}; + +module.exports = ZipFileWorker; + +},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(require,module,exports){ +'use strict'; + +var compressions = require('../compressions'); +var ZipFileWorker = require('./ZipFileWorker'); + +/** + * Find the compression to use. + * @param {String} fileCompression the compression defined at the file level, if any. + * @param {String} zipCompression the compression defined at the load() level. + * @return {Object} the compression object to use. + */ +var getCompression = function (fileCompression, zipCompression) { + + var compressionName = fileCompression || zipCompression; + var compression = compressions[compressionName]; + if (!compression) { + throw new Error(compressionName + " is not a valid compression method !"); + } + return compression; +}; + +/** + * Create a worker to generate a zip file. + * @param {JSZip} zip the JSZip instance at the right root level. + * @param {Object} options to generate the zip file. + * @param {String} comment the comment to use. + */ +exports.generateWorker = function (zip, options, comment) { + + var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName); + var entriesCount = 0; + try { + + zip.forEach(function (relativePath, file) { + entriesCount++; + var compression = getCompression(file.options.compression, options.compression); + var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; + var dir = file.dir, date = file.date; + + file._compressWorker(compression, compressionOptions) + .withStreamInfo("file", { + name : relativePath, + dir : dir, + date : date, + comment : file.comment || "", + unixPermissions : file.unixPermissions, + dosPermissions : file.dosPermissions + }) + .pipe(zipFileWorker); + }); + zipFileWorker.entriesCount = entriesCount; + } catch (e) { + zipFileWorker.error(e); + } + + return zipFileWorker; +}; + +},{"../compressions":3,"./ZipFileWorker":8}],10:[function(require,module,exports){ +'use strict'; + +/** + * Representation a of zip file in js + * @constructor + */ +function JSZip() { + // if this constructor is used without `new`, it adds `new` before itself: + if(!(this instanceof JSZip)) { + return new JSZip(); + } + + if(arguments.length) { + throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); + } + + // object containing the files : + // { + // "folder/" : {...}, + // "folder/data.txt" : {...} + // } + this.files = {}; + + this.comment = null; + + // Where we are in the hierarchy + this.root = ""; + this.clone = function() { + var newObj = new JSZip(); + for (var i in this) { + if (typeof this[i] !== "function") { + newObj[i] = this[i]; + } + } + return newObj; + }; +} +JSZip.prototype = require('./object'); +JSZip.prototype.loadAsync = require('./load'); +JSZip.support = require('./support'); +JSZip.defaults = require('./defaults'); + +// TODO find a better way to handle this version, +// a require('package.json').version doesn't work with webpack, see #327 +JSZip.version = "3.1.5"; + +JSZip.loadAsync = function (content, options) { + return new JSZip().loadAsync(content, options); +}; + +JSZip.external = require("./external"); +module.exports = JSZip; + +},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(require,module,exports){ +'use strict'; +var utils = require('./utils'); +var external = require("./external"); +var utf8 = require('./utf8'); +var utils = require('./utils'); +var ZipEntries = require('./zipEntries'); +var Crc32Probe = require('./stream/Crc32Probe'); +var nodejsUtils = require("./nodejsUtils"); + +/** + * Check the CRC32 of an entry. + * @param {ZipEntry} zipEntry the zip entry to check. + * @return {Promise} the result. + */ +function checkEntryCRC32(zipEntry) { + return new external.Promise(function (resolve, reject) { + var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe()); + worker.on("error", function (e) { + reject(e); + }) + .on("end", function () { + if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) { + reject(new Error("Corrupted zip : CRC32 mismatch")); + } else { + resolve(); + } + }) + .resume(); + }); +} + +module.exports = function(data, options) { + var zip = this; + options = utils.extend(options || {}, { + base64: false, + checkCRC32: false, + optimizedBinaryString: false, + createFolders: false, + decodeFileName: utf8.utf8decode + }); + + if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + return external.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")); + } + + return utils.prepareContent("the loaded zip file", data, true, options.optimizedBinaryString, options.base64) + .then(function(data) { + var zipEntries = new ZipEntries(options); + zipEntries.load(data); + return zipEntries; + }).then(function checkCRC32(zipEntries) { + var promises = [external.Promise.resolve(zipEntries)]; + var files = zipEntries.files; + if (options.checkCRC32) { + for (var i = 0; i < files.length; i++) { + promises.push(checkEntryCRC32(files[i])); + } + } + return external.Promise.all(promises); + }).then(function addFiles(results) { + var zipEntries = results.shift(); + var files = zipEntries.files; + for (var i = 0; i < files.length; i++) { + var input = files[i]; + zip.file(input.fileNameStr, input.decompressed, { + binary: true, + optimizedBinaryString: true, + date: input.date, + dir: input.dir, + comment : input.fileCommentStr.length ? input.fileCommentStr : null, + unixPermissions : input.unixPermissions, + dosPermissions : input.dosPermissions, + createFolders: options.createFolders + }); + } + if (zipEntries.zipComment.length) { + zip.comment = zipEntries.zipComment; + } + + return zip; + }); +}; + +},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(require,module,exports){ +"use strict"; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); + +/** + * A worker that use a nodejs stream as source. + * @constructor + * @param {String} filename the name of the file entry for this stream. + * @param {Readable} stream the nodejs stream. + */ +function NodejsStreamInputAdapter(filename, stream) { + GenericWorker.call(this, "Nodejs stream input adapter for " + filename); + this._upstreamEnded = false; + this._bindStream(stream); +} + +utils.inherits(NodejsStreamInputAdapter, GenericWorker); + +/** + * Prepare the stream and bind the callbacks on it. + * Do this ASAP on node 0.10 ! A lazy binding doesn't always work. + * @param {Stream} stream the nodejs stream to use. + */ +NodejsStreamInputAdapter.prototype._bindStream = function (stream) { + var self = this; + this._stream = stream; + stream.pause(); + stream + .on("data", function (chunk) { + self.push({ + data: chunk, + meta : { + percent : 0 + } + }); + }) + .on("error", function (e) { + if(self.isPaused) { + this.generatedError = e; + } else { + self.error(e); + } + }) + .on("end", function () { + if(self.isPaused) { + self._upstreamEnded = true; + } else { + self.end(); + } + }); +}; +NodejsStreamInputAdapter.prototype.pause = function () { + if(!GenericWorker.prototype.pause.call(this)) { + return false; + } + this._stream.pause(); + return true; +}; +NodejsStreamInputAdapter.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if(this._upstreamEnded) { + this.end(); + } else { + this._stream.resume(); + } + + return true; +}; + +module.exports = NodejsStreamInputAdapter; + +},{"../stream/GenericWorker":28,"../utils":32}],13:[function(require,module,exports){ +'use strict'; + +var Readable = require('readable-stream').Readable; + +var utils = require('../utils'); +utils.inherits(NodejsStreamOutputAdapter, Readable); + +/** +* A nodejs stream using a worker as source. +* @see the SourceWrapper in http://nodejs.org/api/stream.html +* @constructor +* @param {StreamHelper} helper the helper wrapping the worker +* @param {Object} options the nodejs stream options +* @param {Function} updateCb the update callback. +*/ +function NodejsStreamOutputAdapter(helper, options, updateCb) { + Readable.call(this, options); + this._helper = helper; + + var self = this; + helper.on("data", function (data, meta) { + if (!self.push(data)) { + self._helper.pause(); + } + if(updateCb) { + updateCb(meta); + } + }) + .on("error", function(e) { + self.emit('error', e); + }) + .on("end", function () { + self.push(null); + }); +} + + +NodejsStreamOutputAdapter.prototype._read = function() { + this._helper.resume(); +}; + +module.exports = NodejsStreamOutputAdapter; + +},{"../utils":32,"readable-stream":16}],14:[function(require,module,exports){ +'use strict'; + +module.exports = { + /** + * True if this is running in Nodejs, will be undefined in a browser. + * In a browser, browserify won't include this file and the whole module + * will be resolved an empty object. + */ + isNode : typeof Buffer !== "undefined", + /** + * Create a new nodejs Buffer from an existing content. + * @param {Object} data the data to pass to the constructor. + * @param {String} encoding the encoding to use. + * @return {Buffer} a new Buffer. + */ + newBufferFrom: function(data, encoding) { + // XXX We can't use `Buffer.from` which comes from `Uint8Array.from` + // in nodejs v4 (< v.4.5). It's not the expected implementation (and + // has a different signature). + // see https://github.com/nodejs/node/issues/8053 + // A condition on nodejs' version won't solve the issue as we don't + // control the Buffer polyfills that may or may not be used. + return new Buffer(data, encoding); + }, + /** + * Create a new nodejs Buffer with the specified size. + * @param {Integer} size the size of the buffer. + * @return {Buffer} a new Buffer. + */ + allocBuffer: function (size) { + if (Buffer.alloc) { + return Buffer.alloc(size); + } else { + return new Buffer(size); + } + }, + /** + * Find out if an object is a Buffer. + * @param {Object} b the object to test. + * @return {Boolean} true if the object is a Buffer, false otherwise. + */ + isBuffer : function(b){ + return Buffer.isBuffer(b); + }, + + isStream : function (obj) { + return obj && + typeof obj.on === "function" && + typeof obj.pause === "function" && + typeof obj.resume === "function"; + } +}; + +},{}],15:[function(require,module,exports){ +'use strict'; +var utf8 = require('./utf8'); +var utils = require('./utils'); +var GenericWorker = require('./stream/GenericWorker'); +var StreamHelper = require('./stream/StreamHelper'); +var defaults = require('./defaults'); +var CompressedObject = require('./compressedObject'); +var ZipObject = require('./zipObject'); +var generate = require("./generate"); +var nodejsUtils = require("./nodejsUtils"); +var NodejsStreamInputAdapter = require("./nodejs/NodejsStreamInputAdapter"); + + +/** + * Add a file in the current folder. + * @private + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file + * @param {Object} originalOptions the options of the file + * @return {Object} the new file. + */ +var fileAdd = function(name, data, originalOptions) { + // be sure sub folders exist + var dataType = utils.getTypeOf(data), + parent; + + + /* + * Correct options. + */ + + var o = utils.extend(originalOptions || {}, defaults); + o.date = o.date || new Date(); + if (o.compression !== null) { + o.compression = o.compression.toUpperCase(); + } + + if (typeof o.unixPermissions === "string") { + o.unixPermissions = parseInt(o.unixPermissions, 8); + } + + // UNX_IFDIR 0040000 see zipinfo.c + if (o.unixPermissions && (o.unixPermissions & 0x4000)) { + o.dir = true; + } + // Bit 4 Directory + if (o.dosPermissions && (o.dosPermissions & 0x0010)) { + o.dir = true; + } + + if (o.dir) { + name = forceTrailingSlash(name); + } + if (o.createFolders && (parent = parentFolder(name))) { + folderAdd.call(this, parent, true); + } + + var isUnicodeString = dataType === "string" && o.binary === false && o.base64 === false; + if (!originalOptions || typeof originalOptions.binary === "undefined") { + o.binary = !isUnicodeString; + } + + + var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0; + + if (isCompressedEmpty || o.dir || !data || data.length === 0) { + o.base64 = false; + o.binary = true; + data = ""; + o.compression = "STORE"; + dataType = "string"; + } + + /* + * Convert content to fit. + */ + + var zipObjectContent = null; + if (data instanceof CompressedObject || data instanceof GenericWorker) { + zipObjectContent = data; + } else if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + zipObjectContent = new NodejsStreamInputAdapter(name, data); + } else { + zipObjectContent = utils.prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64); + } + + var object = new ZipObject(name, zipObjectContent, o); + this.files[name] = object; + /* + TODO: we can't throw an exception because we have async promises + (we can have a promise of a Date() for example) but returning a + promise is useless because file(name, data) returns the JSZip + object for chaining. Should we break that to allow the user + to catch the error ? + + return external.Promise.resolve(zipObjectContent) + .then(function () { + return object; + }); + */ +}; + +/** + * Find the parent folder of the path. + * @private + * @param {string} path the path to use + * @return {string} the parent folder, or "" + */ +var parentFolder = function (path) { + if (path.slice(-1) === '/') { + path = path.substring(0, path.length - 1); + } + var lastSlash = path.lastIndexOf('/'); + return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; +}; + +/** + * Returns the path with a slash at the end. + * @private + * @param {String} path the path to check. + * @return {String} the path with a trailing slash. + */ +var forceTrailingSlash = function(path) { + // Check the name ends with a / + if (path.slice(-1) !== "/") { + path += "/"; // IE doesn't like substr(-1) + } + return path; +}; + +/** + * Add a (sub) folder in the current folder. + * @private + * @param {string} name the folder's name + * @param {boolean=} [createFolders] If true, automatically create sub + * folders. Defaults to false. + * @return {Object} the new folder. + */ +var folderAdd = function(name, createFolders) { + createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders; + + name = forceTrailingSlash(name); + + // Does this folder already exist? + if (!this.files[name]) { + fileAdd.call(this, name, null, { + dir: true, + createFolders: createFolders + }); + } + return this.files[name]; +}; + +/** +* Cross-window, cross-Node-context regular expression detection +* @param {Object} object Anything +* @return {Boolean} true if the object is a regular expression, +* false otherwise +*/ +function isRegExp(object) { + return Object.prototype.toString.call(object) === "[object RegExp]"; +} + +// return the actual prototype of JSZip +var out = { + /** + * @see loadAsync + */ + load: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + + /** + * Call a callback function for each entry at this folder level. + * @param {Function} cb the callback function: + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + */ + forEach: function(cb) { + var filename, relativePath, file; + for (filename in this.files) { + if (!this.files.hasOwnProperty(filename)) { + continue; + } + file = this.files[filename]; + relativePath = filename.slice(this.root.length, filename.length); + if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root + cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn... + } + } + }, + + /** + * Filter nested files/folders with the specified function. + * @param {Function} search the predicate to use : + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + * @return {Array} An array of matching elements. + */ + filter: function(search) { + var result = []; + this.forEach(function (relativePath, entry) { + if (search(relativePath, entry)) { // the file matches the function + result.push(entry); + } + + }); + return result; + }, + + /** + * Add a file to the zip file, or search a file. + * @param {string|RegExp} name The name of the file to add (if data is defined), + * the name of the file to find (if no data) or a regex to match files. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded + * @param {Object} o File options + * @return {JSZip|Object|Array} this JSZip object (when adding a file), + * a file (when searching by string) or an array of files (when searching by regex). + */ + file: function(name, data, o) { + if (arguments.length === 1) { + if (isRegExp(name)) { + var regexp = name; + return this.filter(function(relativePath, file) { + return !file.dir && regexp.test(relativePath); + }); + } + else { // text + var obj = this.files[this.root + name]; + if (obj && !obj.dir) { + return obj; + } else { + return null; + } + } + } + else { // more than one argument : we have data ! + name = this.root + name; + fileAdd.call(this, name, data, o); + } + return this; + }, + + /** + * Add a directory to the zip file, or search. + * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. + * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. + */ + folder: function(arg) { + if (!arg) { + return this; + } + + if (isRegExp(arg)) { + return this.filter(function(relativePath, file) { + return file.dir && arg.test(relativePath); + }); + } + + // else, name is a new folder + var name = this.root + arg; + var newFolder = folderAdd.call(this, name); + + // Allow chaining by returning a new object with this folder as the root + var ret = this.clone(); + ret.root = newFolder.name; + return ret; + }, + + /** + * Delete a file, or a directory and all sub-files, from the zip + * @param {string} name the name of the file to delete + * @return {JSZip} this JSZip object + */ + remove: function(name) { + name = this.root + name; + var file = this.files[name]; + if (!file) { + // Look for any folders + if (name.slice(-1) !== "/") { + name += "/"; + } + file = this.files[name]; + } + + if (file && !file.dir) { + // file + delete this.files[name]; + } else { + // maybe a folder, delete recursively + var kids = this.filter(function(relativePath, file) { + return file.name.slice(0, name.length) === name; + }); + for (var i = 0; i < kids.length; i++) { + delete this.files[kids[i].name]; + } + } + + return this; + }, + + /** + * Generate the complete zip file + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file + */ + generate: function(options) { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + /** + * Generate the complete zip file as an internal stream. + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {StreamHelper} the streamed zip file. + */ + generateInternalStream: function(options) { + var worker, opts = {}; + try { + opts = utils.extend(options || {}, { + streamFiles: false, + compression: "STORE", + compressionOptions : null, + type: "", + platform: "DOS", + comment: null, + mimeType: 'application/zip', + encodeFileName: utf8.utf8encode + }); + + opts.type = opts.type.toLowerCase(); + opts.compression = opts.compression.toUpperCase(); + + // "binarystring" is prefered but the internals use "string". + if(opts.type === "binarystring") { + opts.type = "string"; + } + + if (!opts.type) { + throw new Error("No output type specified."); + } + + utils.checkSupport(opts.type); + + // accept nodejs `process.platform` + if( + opts.platform === 'darwin' || + opts.platform === 'freebsd' || + opts.platform === 'linux' || + opts.platform === 'sunos' + ) { + opts.platform = "UNIX"; + } + if (opts.platform === 'win32') { + opts.platform = "DOS"; + } + + var comment = opts.comment || this.comment || ""; + worker = generate.generateWorker(this, opts, comment); + } catch (e) { + worker = new GenericWorker("error"); + worker.error(e); + } + return new StreamHelper(worker, opts.type || "string", opts.mimeType); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateAsync: function(options, onUpdate) { + return this.generateInternalStream(options).accumulate(onUpdate); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateNodeStream: function(options, onUpdate) { + options = options || {}; + if (!options.type) { + options.type = "nodebuffer"; + } + return this.generateInternalStream(options).toNodejsStream(onUpdate); + } +}; +module.exports = out; + +},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(require,module,exports){ +/* + * This file is used by module bundlers (browserify/webpack/etc) when + * including a stream implementation. We use "readable-stream" to get a + * consistent behavior between nodejs versions but bundlers often have a shim + * for "stream". Using this shim greatly improve the compatibility and greatly + * reduce the final size of the bundle (only one stream implementation, not + * two). + */ +module.exports = require("stream"); + +},{"stream":undefined}],17:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function ArrayReader(data) { + DataReader.call(this, data); + for(var i = 0; i < this.data.length; i++) { + data[i] = data[i] & 0xFF; + } +} +utils.inherits(ArrayReader, DataReader); +/** + * @see DataReader.byteAt + */ +ArrayReader.prototype.byteAt = function(i) { + return this.data[this.zero + i]; +}; +/** + * @see DataReader.lastIndexOfSignature + */ +ArrayReader.prototype.lastIndexOfSignature = function(sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3); + for (var i = this.length - 4; i >= 0; --i) { + if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { + return i - this.zero; + } + } + + return -1; +}; +/** + * @see DataReader.readAndCheckSignature + */ +ArrayReader.prototype.readAndCheckSignature = function (sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3), + data = this.readData(4); + return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3]; +}; +/** + * @see DataReader.readData + */ +ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + return []; + } + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = ArrayReader; + +},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){ +'use strict'; +var utils = require('../utils'); + +function DataReader(data) { + this.data = data; // type : see implementation + this.length = data.length; + this.index = 0; + this.zero = 0; +} +DataReader.prototype = { + /** + * Check that the offset will not go too far. + * @param {string} offset the additional offset to check. + * @throws {Error} an Error if the offset is out of bounds. + */ + checkOffset: function(offset) { + this.checkIndex(this.index + offset); + }, + /** + * Check that the specified index will not be too far. + * @param {string} newIndex the index to check. + * @throws {Error} an Error if the index is out of bounds. + */ + checkIndex: function(newIndex) { + if (this.length < this.zero + newIndex || newIndex < 0) { + throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); + } + }, + /** + * Change the index. + * @param {number} newIndex The new index. + * @throws {Error} if the new index is out of the data. + */ + setIndex: function(newIndex) { + this.checkIndex(newIndex); + this.index = newIndex; + }, + /** + * Skip the next n bytes. + * @param {number} n the number of bytes to skip. + * @throws {Error} if the new index is out of the data. + */ + skip: function(n) { + this.setIndex(this.index + n); + }, + /** + * Get the byte at the specified index. + * @param {number} i the index to use. + * @return {number} a byte. + */ + byteAt: function(i) { + // see implementations + }, + /** + * Get the next number with a given byte size. + * @param {number} size the number of bytes to read. + * @return {number} the corresponding number. + */ + readInt: function(size) { + var result = 0, + i; + this.checkOffset(size); + for (i = this.index + size - 1; i >= this.index; i--) { + result = (result << 8) + this.byteAt(i); + } + this.index += size; + return result; + }, + /** + * Get the next string with a given byte size. + * @param {number} size the number of bytes to read. + * @return {string} the corresponding string. + */ + readString: function(size) { + return utils.transformTo("string", this.readData(size)); + }, + /** + * Get raw data without conversion, bytes. + * @param {number} size the number of bytes to read. + * @return {Object} the raw data, implementation specific. + */ + readData: function(size) { + // see implementations + }, + /** + * Find the last occurence of a zip signature (4 bytes). + * @param {string} sig the signature to find. + * @return {number} the index of the last occurence, -1 if not found. + */ + lastIndexOfSignature: function(sig) { + // see implementations + }, + /** + * Read the signature (4 bytes) at the current position and compare it with sig. + * @param {string} sig the expected signature + * @return {boolean} true if the signature matches, false otherwise. + */ + readAndCheckSignature: function(sig) { + // see implementations + }, + /** + * Get the next date. + * @return {Date} the date. + */ + readDate: function() { + var dostime = this.readInt(4); + return new Date(Date.UTC( + ((dostime >> 25) & 0x7f) + 1980, // year + ((dostime >> 21) & 0x0f) - 1, // month + (dostime >> 16) & 0x1f, // day + (dostime >> 11) & 0x1f, // hour + (dostime >> 5) & 0x3f, // minute + (dostime & 0x1f) << 1)); // second + } +}; +module.exports = DataReader; + +},{"../utils":32}],19:[function(require,module,exports){ +'use strict'; +var Uint8ArrayReader = require('./Uint8ArrayReader'); +var utils = require('../utils'); + +function NodeBufferReader(data) { + Uint8ArrayReader.call(this, data); +} +utils.inherits(NodeBufferReader, Uint8ArrayReader); + +/** + * @see DataReader.readData + */ +NodeBufferReader.prototype.readData = function(size) { + this.checkOffset(size); + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = NodeBufferReader; + +},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function StringReader(data) { + DataReader.call(this, data); +} +utils.inherits(StringReader, DataReader); +/** + * @see DataReader.byteAt + */ +StringReader.prototype.byteAt = function(i) { + return this.data.charCodeAt(this.zero + i); +}; +/** + * @see DataReader.lastIndexOfSignature + */ +StringReader.prototype.lastIndexOfSignature = function(sig) { + return this.data.lastIndexOf(sig) - this.zero; +}; +/** + * @see DataReader.readAndCheckSignature + */ +StringReader.prototype.readAndCheckSignature = function (sig) { + var data = this.readData(4); + return sig === data; +}; +/** + * @see DataReader.readData + */ +StringReader.prototype.readData = function(size) { + this.checkOffset(size); + // this will work because the constructor applied the "& 0xff" mask. + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = StringReader; + +},{"../utils":32,"./DataReader":18}],21:[function(require,module,exports){ +'use strict'; +var ArrayReader = require('./ArrayReader'); +var utils = require('../utils'); + +function Uint8ArrayReader(data) { + ArrayReader.call(this, data); +} +utils.inherits(Uint8ArrayReader, ArrayReader); +/** + * @see DataReader.readData + */ +Uint8ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. + return new Uint8Array(0); + } + var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = Uint8ArrayReader; + +},{"../utils":32,"./ArrayReader":17}],22:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var support = require('../support'); +var ArrayReader = require('./ArrayReader'); +var StringReader = require('./StringReader'); +var NodeBufferReader = require('./NodeBufferReader'); +var Uint8ArrayReader = require('./Uint8ArrayReader'); + +/** + * Create a reader adapted to the data. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read. + * @return {DataReader} the data reader. + */ +module.exports = function (data) { + var type = utils.getTypeOf(data); + utils.checkSupport(type); + if (type === "string" && !support.uint8array) { + return new StringReader(data); + } + if (type === "nodebuffer") { + return new NodeBufferReader(data); + } + if (support.uint8array) { + return new Uint8ArrayReader(utils.transformTo("uint8array", data)); + } + return new ArrayReader(utils.transformTo("array", data)); +}; + +},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(require,module,exports){ +'use strict'; +exports.LOCAL_FILE_HEADER = "PK\x03\x04"; +exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; +exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; +exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; +exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; +exports.DATA_DESCRIPTOR = "PK\x07\x08"; + +},{}],24:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var utils = require('../utils'); + +/** + * A worker which convert chunks to a specified type. + * @constructor + * @param {String} destType the destination type. + */ +function ConvertWorker(destType) { + GenericWorker.call(this, "ConvertWorker to " + destType); + this.destType = destType; +} +utils.inherits(ConvertWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +ConvertWorker.prototype.processChunk = function (chunk) { + this.push({ + data : utils.transformTo(this.destType, chunk.data), + meta : chunk.meta + }); +}; +module.exports = ConvertWorker; + +},{"../utils":32,"./GenericWorker":28}],25:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var crc32 = require('../crc32'); +var utils = require('../utils'); + +/** + * A worker which calculate the crc32 of the data flowing through. + * @constructor + */ +function Crc32Probe() { + GenericWorker.call(this, "Crc32Probe"); + this.withStreamInfo("crc32", 0); +} +utils.inherits(Crc32Probe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Crc32Probe.prototype.processChunk = function (chunk) { + this.streamInfo.crc32 = crc32(chunk.data, this.streamInfo.crc32 || 0); + this.push(chunk); +}; +module.exports = Crc32Probe; + +},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +/** + * A worker which calculate the total length of the data flowing through. + * @constructor + * @param {String} propName the name used to expose the length + */ +function DataLengthProbe(propName) { + GenericWorker.call(this, "DataLengthProbe for " + propName); + this.propName = propName; + this.withStreamInfo(propName, 0); +} +utils.inherits(DataLengthProbe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +DataLengthProbe.prototype.processChunk = function (chunk) { + if(chunk) { + var length = this.streamInfo[this.propName] || 0; + this.streamInfo[this.propName] = length + chunk.data.length; + } + GenericWorker.prototype.processChunk.call(this, chunk); +}; +module.exports = DataLengthProbe; + + +},{"../utils":32,"./GenericWorker":28}],27:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +// the size of the generated chunks +// TODO expose this as a public variable +var DEFAULT_BLOCK_SIZE = 16 * 1024; + +/** + * A worker that reads a content and emits chunks. + * @constructor + * @param {Promise} dataP the promise of the data to split + */ +function DataWorker(dataP) { + GenericWorker.call(this, "DataWorker"); + var self = this; + this.dataIsReady = false; + this.index = 0; + this.max = 0; + this.data = null; + this.type = ""; + + this._tickScheduled = false; + + dataP.then(function (data) { + self.dataIsReady = true; + self.data = data; + self.max = data && data.length || 0; + self.type = utils.getTypeOf(data); + if(!self.isPaused) { + self._tickAndRepeat(); + } + }, function (e) { + self.error(e); + }); +} + +utils.inherits(DataWorker, GenericWorker); + +/** + * @see GenericWorker.cleanUp + */ +DataWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this.data = null; +}; + +/** + * @see GenericWorker.resume + */ +DataWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this._tickScheduled && this.dataIsReady) { + this._tickScheduled = true; + utils.delay(this._tickAndRepeat, [], this); + } + return true; +}; + +/** + * Trigger a tick a schedule an other call to this function. + */ +DataWorker.prototype._tickAndRepeat = function() { + this._tickScheduled = false; + if(this.isPaused || this.isFinished) { + return; + } + this._tick(); + if(!this.isFinished) { + utils.delay(this._tickAndRepeat, [], this); + this._tickScheduled = true; + } +}; + +/** + * Read and push a chunk. + */ +DataWorker.prototype._tick = function() { + + if(this.isPaused || this.isFinished) { + return false; + } + + var size = DEFAULT_BLOCK_SIZE; + var data = null, nextIndex = Math.min(this.max, this.index + size); + if (this.index >= this.max) { + // EOF + return this.end(); + } else { + switch(this.type) { + case "string": + data = this.data.substring(this.index, nextIndex); + break; + case "uint8array": + data = this.data.subarray(this.index, nextIndex); + break; + case "array": + case "nodebuffer": + data = this.data.slice(this.index, nextIndex); + break; + } + this.index = nextIndex; + return this.push({ + data : data, + meta : { + percent : this.max ? this.index / this.max * 100 : 0 + } + }); + } +}; + +module.exports = DataWorker; + +},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){ +'use strict'; + +/** + * A worker that does nothing but passing chunks to the next one. This is like + * a nodejs stream but with some differences. On the good side : + * - it works on IE 6-9 without any issue / polyfill + * - it weights less than the full dependencies bundled with browserify + * - it forwards errors (no need to declare an error handler EVERYWHERE) + * + * A chunk is an object with 2 attributes : `meta` and `data`. The former is an + * object containing anything (`percent` for example), see each worker for more + * details. The latter is the real data (String, Uint8Array, etc). + * + * @constructor + * @param {String} name the name of the stream (mainly used for debugging purposes) + */ +function GenericWorker(name) { + // the name of the worker + this.name = name || "default"; + // an object containing metadata about the workers chain + this.streamInfo = {}; + // an error which happened when the worker was paused + this.generatedError = null; + // an object containing metadata to be merged by this worker into the general metadata + this.extraStreamInfo = {}; + // true if the stream is paused (and should not do anything), false otherwise + this.isPaused = true; + // true if the stream is finished (and should not do anything), false otherwise + this.isFinished = false; + // true if the stream is locked to prevent further structure updates (pipe), false otherwise + this.isLocked = false; + // the event listeners + this._listeners = { + 'data':[], + 'end':[], + 'error':[] + }; + // the previous worker, if any + this.previous = null; +} + +GenericWorker.prototype = { + /** + * Push a chunk to the next workers. + * @param {Object} chunk the chunk to push + */ + push : function (chunk) { + this.emit("data", chunk); + }, + /** + * End the stream. + * @return {Boolean} true if this call ended the worker, false otherwise. + */ + end : function () { + if (this.isFinished) { + return false; + } + + this.flush(); + try { + this.emit("end"); + this.cleanUp(); + this.isFinished = true; + } catch (e) { + this.emit("error", e); + } + return true; + }, + /** + * End the stream with an error. + * @param {Error} e the error which caused the premature end. + * @return {Boolean} true if this call ended the worker with an error, false otherwise. + */ + error : function (e) { + if (this.isFinished) { + return false; + } + + if(this.isPaused) { + this.generatedError = e; + } else { + this.isFinished = true; + + this.emit("error", e); + + // in the workers chain exploded in the middle of the chain, + // the error event will go downward but we also need to notify + // workers upward that there has been an error. + if(this.previous) { + this.previous.error(e); + } + + this.cleanUp(); + } + return true; + }, + /** + * Add a callback on an event. + * @param {String} name the name of the event (data, end, error) + * @param {Function} listener the function to call when the event is triggered + * @return {GenericWorker} the current object for chainability + */ + on : function (name, listener) { + this._listeners[name].push(listener); + return this; + }, + /** + * Clean any references when a worker is ending. + */ + cleanUp : function () { + this.streamInfo = this.generatedError = this.extraStreamInfo = null; + this._listeners = []; + }, + /** + * Trigger an event. This will call registered callback with the provided arg. + * @param {String} name the name of the event (data, end, error) + * @param {Object} arg the argument to call the callback with. + */ + emit : function (name, arg) { + if (this._listeners[name]) { + for(var i = 0; i < this._listeners[name].length; i++) { + this._listeners[name][i].call(this, arg); + } + } + }, + /** + * Chain a worker with an other. + * @param {Worker} next the worker receiving events from the current one. + * @return {worker} the next worker for chainability + */ + pipe : function (next) { + return next.registerPrevious(this); + }, + /** + * Same as `pipe` in the other direction. + * Using an API with `pipe(next)` is very easy. + * Implementing the API with the point of view of the next one registering + * a source is easier, see the ZipFileWorker. + * @param {Worker} previous the previous worker, sending events to this one + * @return {Worker} the current worker for chainability + */ + registerPrevious : function (previous) { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + + // sharing the streamInfo... + this.streamInfo = previous.streamInfo; + // ... and adding our own bits + this.mergeStreamInfo(); + this.previous = previous; + var self = this; + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.end(); + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; + }, + /** + * Pause the stream so it doesn't send events anymore. + * @return {Boolean} true if this call paused the worker, false otherwise. + */ + pause : function () { + if(this.isPaused || this.isFinished) { + return false; + } + this.isPaused = true; + + if(this.previous) { + this.previous.pause(); + } + return true; + }, + /** + * Resume a paused stream. + * @return {Boolean} true if this call resumed the worker, false otherwise. + */ + resume : function () { + if(!this.isPaused || this.isFinished) { + return false; + } + this.isPaused = false; + + // if true, the worker tried to resume but failed + var withError = false; + if(this.generatedError) { + this.error(this.generatedError); + withError = true; + } + if(this.previous) { + this.previous.resume(); + } + + return !withError; + }, + /** + * Flush any remaining bytes as the stream is ending. + */ + flush : function () {}, + /** + * Process a chunk. This is usually the method overridden. + * @param {Object} chunk the chunk to process. + */ + processChunk : function(chunk) { + this.push(chunk); + }, + /** + * Add a key/value to be added in the workers chain streamInfo once activated. + * @param {String} key the key to use + * @param {Object} value the associated value + * @return {Worker} the current worker for chainability + */ + withStreamInfo : function (key, value) { + this.extraStreamInfo[key] = value; + this.mergeStreamInfo(); + return this; + }, + /** + * Merge this worker's streamInfo into the chain's streamInfo. + */ + mergeStreamInfo : function () { + for(var key in this.extraStreamInfo) { + if (!this.extraStreamInfo.hasOwnProperty(key)) { + continue; + } + this.streamInfo[key] = this.extraStreamInfo[key]; + } + }, + + /** + * Lock the stream to prevent further updates on the workers chain. + * After calling this method, all calls to pipe will fail. + */ + lock: function () { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + this.isLocked = true; + if (this.previous) { + this.previous.lock(); + } + }, + + /** + * + * Pretty print the workers chain. + */ + toString : function () { + var me = "Worker " + this.name; + if (this.previous) { + return this.previous + " -> " + me; + } else { + return me; + } + } +}; + +module.exports = GenericWorker; + +},{}],29:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var ConvertWorker = require('./ConvertWorker'); +var GenericWorker = require('./GenericWorker'); +var base64 = require('../base64'); +var support = require("../support"); +var external = require("../external"); + +var NodejsStreamOutputAdapter = null; +if (support.nodestream) { + try { + NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter'); + } catch(e) {} +} + +/** + * Apply the final transformation of the data. If the user wants a Blob for + * example, it's easier to work with an U8intArray and finally do the + * ArrayBuffer/Blob conversion. + * @param {String} type the name of the final type + * @param {String|Uint8Array|Buffer} content the content to transform + * @param {String} mimeType the mime type of the content, if applicable. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. + */ +function transformZipOutput(type, content, mimeType) { + switch(type) { + case "blob" : + return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); + case "base64" : + return base64.encode(content); + default : + return utils.transformTo(type, content); + } +} + +/** + * Concatenate an array of data of the given type. + * @param {String} type the type of the data in the given array. + * @param {Array} dataArray the array containing the data chunks to concatenate + * @return {String|Uint8Array|Buffer} the concatenated data + * @throws Error if the asked type is unsupported + */ +function concat (type, dataArray) { + var i, index = 0, res = null, totalLength = 0; + for(i = 0; i < dataArray.length; i++) { + totalLength += dataArray[i].length; + } + switch(type) { + case "string": + return dataArray.join(""); + case "array": + return Array.prototype.concat.apply([], dataArray); + case "uint8array": + res = new Uint8Array(totalLength); + for(i = 0; i < dataArray.length; i++) { + res.set(dataArray[i], index); + index += dataArray[i].length; + } + return res; + case "nodebuffer": + return Buffer.concat(dataArray); + default: + throw new Error("concat : unsupported type '" + type + "'"); + } +} + +/** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {StreamHelper} helper the helper to use. + * @param {Function} updateCallback a callback called on each update. Called + * with one arg : + * - the metadata linked to the update received. + * @return Promise the promise for the accumulation. + */ +function accumulate(helper, updateCallback) { + return new external.Promise(function (resolve, reject){ + var dataArray = []; + var chunkType = helper._internalType, + resultType = helper._outputType, + mimeType = helper._mimeType; + helper + .on('data', function (data, meta) { + dataArray.push(data); + if(updateCallback) { + updateCallback(meta); + } + }) + .on('error', function(err) { + dataArray = []; + reject(err); + }) + .on('end', function (){ + try { + var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); + resolve(result); + } catch (e) { + reject(e); + } + dataArray = []; + }) + .resume(); + }); +} + +/** + * An helper to easily use workers outside of JSZip. + * @constructor + * @param {Worker} worker the worker to wrap + * @param {String} outputType the type of data expected by the use + * @param {String} mimeType the mime type of the content, if applicable. + */ +function StreamHelper(worker, outputType, mimeType) { + var internalType = outputType; + switch(outputType) { + case "blob": + case "arraybuffer": + internalType = "uint8array"; + break; + case "base64": + internalType = "string"; + break; + } + + try { + // the type used internally + this._internalType = internalType; + // the type used to output results + this._outputType = outputType; + // the mime type + this._mimeType = mimeType; + utils.checkSupport(internalType); + this._worker = worker.pipe(new ConvertWorker(internalType)); + // the last workers can be rewired without issues but we need to + // prevent any updates on previous workers. + worker.lock(); + } catch(e) { + this._worker = new GenericWorker("error"); + this._worker.error(e); + } +} + +StreamHelper.prototype = { + /** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {Function} updateCb the update callback. + * @return Promise the promise for the accumulation. + */ + accumulate : function (updateCb) { + return accumulate(this, updateCb); + }, + /** + * Add a listener on an event triggered on a stream. + * @param {String} evt the name of the event + * @param {Function} fn the listener + * @return {StreamHelper} the current helper. + */ + on : function (evt, fn) { + var self = this; + + if(evt === "data") { + this._worker.on(evt, function (chunk) { + fn.call(self, chunk.data, chunk.meta); + }); + } else { + this._worker.on(evt, function () { + utils.delay(fn, arguments, self); + }); + } + return this; + }, + /** + * Resume the flow of chunks. + * @return {StreamHelper} the current helper. + */ + resume : function () { + utils.delay(this._worker.resume, [], this._worker); + return this; + }, + /** + * Pause the flow of chunks. + * @return {StreamHelper} the current helper. + */ + pause : function () { + this._worker.pause(); + return this; + }, + /** + * Return a nodejs stream for this helper. + * @param {Function} updateCb the update callback. + * @return {NodejsStreamOutputAdapter} the nodejs stream. + */ + toNodejsStream : function (updateCb) { + utils.checkSupport("nodestream"); + if (this._outputType !== "nodebuffer") { + // an object stream containing blob/arraybuffer/uint8array/string + // is strange and I don't know if it would be useful. + // I you find this comment and have a good usecase, please open a + // bug report ! + throw new Error(this._outputType + " is not supported by this method"); + } + + return new NodejsStreamOutputAdapter(this, { + objectMode : this._outputType !== "nodebuffer" + }, updateCb); + } +}; + + +module.exports = StreamHelper; + +},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(require,module,exports){ +'use strict'; + +exports.base64 = true; +exports.array = true; +exports.string = true; +exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; +exports.nodebuffer = typeof Buffer !== "undefined"; +// contains true if JSZip can read/generate Uint8Array, false otherwise. +exports.uint8array = typeof Uint8Array !== "undefined"; + +if (typeof ArrayBuffer === "undefined") { + exports.blob = false; +} +else { + var buffer = new ArrayBuffer(0); + try { + exports.blob = new Blob([buffer], { + type: "application/zip" + }).size === 0; + } + catch (e) { + try { + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + exports.blob = builder.getBlob('application/zip').size === 0; + } + catch (e) { + exports.blob = false; + } + } +} + +try { + exports.nodestream = !!require('readable-stream').Readable; +} catch(e) { + exports.nodestream = false; +} + +},{"readable-stream":16}],31:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var support = require('./support'); +var nodejsUtils = require('./nodejsUtils'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * The following functions come from pako, from pako/lib/utils/strings + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new Array(256); +for (var i=0; i<256; i++) { + _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); +} +_utf8len[254]=_utf8len[254]=1; // Invalid sequence start + +// convert string to array (typed, when possible) +var string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + if (support.uint8array) { + buf = new Uint8Array(buf_len); + } else { + buf = new Array(buf_len); + } + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +var utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +// convert array to string +var buf2string = function (buf) { + var str, i, out, c, c_len; + var len = buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + // shrinkBuf(utf16buf, out) + if (utf16buf.length !== out) { + if(utf16buf.subarray) { + utf16buf = utf16buf.subarray(0, out); + } else { + utf16buf.length = out; + } + } + + // return String.fromCharCode.apply(null, utf16buf); + return utils.applyFromCharCode(utf16buf); +}; + + +// That's all for the pako functions. + + +/** + * Transform a javascript string into an array (typed if possible) of bytes, + * UTF-8 encoded. + * @param {String} str the string to encode + * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. + */ +exports.utf8encode = function utf8encode(str) { + if (support.nodebuffer) { + return nodejsUtils.newBufferFrom(str, "utf-8"); + } + + return string2buf(str); +}; + + +/** + * Transform a bytes array (or a representation) representing an UTF-8 encoded + * string into a javascript string. + * @param {Array|Uint8Array|Buffer} buf the data de decode + * @return {String} the decoded string. + */ +exports.utf8decode = function utf8decode(buf) { + if (support.nodebuffer) { + return utils.transformTo("nodebuffer", buf).toString("utf-8"); + } + + buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); + + return buf2string(buf); +}; + +/** + * A worker to decode utf8 encoded binary chunks into string chunks. + * @constructor + */ +function Utf8DecodeWorker() { + GenericWorker.call(this, "utf-8 decode"); + // the last bytes if a chunk didn't end with a complete codepoint. + this.leftOver = null; +} +utils.inherits(Utf8DecodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8DecodeWorker.prototype.processChunk = function (chunk) { + + var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data); + + // 1st step, re-use what's left of the previous chunk + if (this.leftOver && this.leftOver.length) { + if(support.uint8array) { + var previousData = data; + data = new Uint8Array(previousData.length + this.leftOver.length); + data.set(this.leftOver, 0); + data.set(previousData, this.leftOver.length); + } else { + data = this.leftOver.concat(data); + } + this.leftOver = null; + } + + var nextBoundary = utf8border(data); + var usableData = data; + if (nextBoundary !== data.length) { + if (support.uint8array) { + usableData = data.subarray(0, nextBoundary); + this.leftOver = data.subarray(nextBoundary, data.length); + } else { + usableData = data.slice(0, nextBoundary); + this.leftOver = data.slice(nextBoundary, data.length); + } + } + + this.push({ + data : exports.utf8decode(usableData), + meta : chunk.meta + }); +}; + +/** + * @see GenericWorker.flush + */ +Utf8DecodeWorker.prototype.flush = function () { + if(this.leftOver && this.leftOver.length) { + this.push({ + data : exports.utf8decode(this.leftOver), + meta : {} + }); + this.leftOver = null; + } +}; +exports.Utf8DecodeWorker = Utf8DecodeWorker; + +/** + * A worker to endcode string chunks into utf8 encoded binary chunks. + * @constructor + */ +function Utf8EncodeWorker() { + GenericWorker.call(this, "utf-8 encode"); +} +utils.inherits(Utf8EncodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8EncodeWorker.prototype.processChunk = function (chunk) { + this.push({ + data : exports.utf8encode(chunk.data), + meta : chunk.meta + }); +}; +exports.Utf8EncodeWorker = Utf8EncodeWorker; + +},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){ +'use strict'; + +var support = require('./support'); +var base64 = require('./base64'); +var nodejsUtils = require('./nodejsUtils'); +var setImmediate = require('core-js/library/fn/set-immediate'); +var external = require("./external"); + + +/** + * Convert a string that pass as a "binary string": it should represent a byte + * array but may have > 255 char codes. Be sure to take only the first byte + * and returns the byte array. + * @param {String} str the string to transform. + * @return {Array|Uint8Array} the string in a binary format. + */ +function string2binary(str) { + var result = null; + if (support.uint8array) { + result = new Uint8Array(str.length); + } else { + result = new Array(str.length); + } + return stringToArrayLike(str, result); +} + +/** + * Create a new blob with the given content and the given type. + * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use + * an Uint8Array because the stock browser of android 4 won't accept it (it + * will be silently converted to a string, "[object Uint8Array]"). + * + * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: + * when a large amount of Array is used to create the Blob, the amount of + * memory consumed is nearly 100 times the original data amount. + * + * @param {String} type the mime type of the blob. + * @return {Blob} the created blob. + */ +exports.newBlob = function(part, type) { + exports.checkSupport("blob"); + + try { + // Blob constructor + return new Blob([part], { + type: type + }); + } + catch (e) { + + try { + // deprecated, browser only, old way + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(part); + return builder.getBlob(type); + } + catch (e) { + + // well, fuck ?! + throw new Error("Bug : can't construct the Blob."); + } + } + + +}; +/** + * The identity function. + * @param {Object} input the input. + * @return {Object} the same input. + */ +function identity(input) { + return input; +} + +/** + * Fill in an array with a string. + * @param {String} str the string to use. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. + */ +function stringToArrayLike(str, array) { + for (var i = 0; i < str.length; ++i) { + array[i] = str.charCodeAt(i) & 0xFF; + } + return array; +} + +/** + * An helper for the function arrayLikeToString. + * This contains static informations and functions that + * can be optimized by the browser JIT compiler. + */ +var arrayToStringHelper = { + /** + * Transform an array of int into a string, chunk by chunk. + * See the performances notes on arrayLikeToString. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @param {String} type the type of the array. + * @param {Integer} chunk the chunk size. + * @return {String} the resulting string. + * @throws Error if the chunk is too big for the stack. + */ + stringifyByChunk: function(array, type, chunk) { + var result = [], k = 0, len = array.length; + // shortcut + if (len <= chunk) { + return String.fromCharCode.apply(null, array); + } + while (k < len) { + if (type === "array" || type === "nodebuffer") { + result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); + } + else { + result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); + } + k += chunk; + } + return result.join(""); + }, + /** + * Call String.fromCharCode on every item in the array. + * This is the naive implementation, which generate A LOT of intermediate string. + * This should be used when everything else fail. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ + stringifyByChar: function(array){ + var resultStr = ""; + for(var i = 0; i < array.length; i++) { + resultStr += String.fromCharCode(array[i]); + } + return resultStr; + }, + applyCanBeUsed : { + /** + * true if the browser accepts to use String.fromCharCode on Uint8Array + */ + uint8array : (function () { + try { + return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; + } catch (e) { + return false; + } + })(), + /** + * true if the browser accepts to use String.fromCharCode on nodejs Buffer. + */ + nodebuffer : (function () { + try { + return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; + } catch (e) { + return false; + } + })() + } +}; + +/** + * Transform an array-like object to a string. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ +function arrayLikeToString(array) { + // Performances notes : + // -------------------- + // String.fromCharCode.apply(null, array) is the fastest, see + // see http://jsperf.com/converting-a-uint8array-to-a-string/2 + // but the stack is limited (and we can get huge arrays !). + // + // result += String.fromCharCode(array[i]); generate too many strings ! + // + // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 + // TODO : we now have workers that split the work. Do we still need that ? + var chunk = 65536, + type = exports.getTypeOf(array), + canUseApply = true; + if (type === "uint8array") { + canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; + } else if (type === "nodebuffer") { + canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; + } + + if (canUseApply) { + while (chunk > 1) { + try { + return arrayToStringHelper.stringifyByChunk(array, type, chunk); + } catch (e) { + chunk = Math.floor(chunk / 2); + } + } + } + + // no apply or chunk error : slow and painful algorithm + // default browser on android 4.* + return arrayToStringHelper.stringifyByChar(array); +} + +exports.applyFromCharCode = arrayLikeToString; + + +/** + * Copy the data from an array-like to an other array-like. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. + */ +function arrayLikeToArrayLike(arrayFrom, arrayTo) { + for (var i = 0; i < arrayFrom.length; i++) { + arrayTo[i] = arrayFrom[i]; + } + return arrayTo; +} + +// a matrix containing functions to transform everything into everything. +var transform = {}; + +// string to ? +transform["string"] = { + "string": identity, + "array": function(input) { + return stringToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["string"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return stringToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": function(input) { + return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); + } +}; + +// array to ? +transform["array"] = { + "string": arrayLikeToString, + "array": identity, + "arraybuffer": function(input) { + return (new Uint8Array(input)).buffer; + }, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// arraybuffer to ? +transform["arraybuffer"] = { + "string": function(input) { + return arrayLikeToString(new Uint8Array(input)); + }, + "array": function(input) { + return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); + }, + "arraybuffer": identity, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(new Uint8Array(input)); + } +}; + +// uint8array to ? +transform["uint8array"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return input.buffer; + }, + "uint8array": identity, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// nodebuffer to ? +transform["nodebuffer"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["nodebuffer"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return arrayLikeToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": identity +}; + +/** + * Transform an input into any type. + * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. + * If no output type is specified, the unmodified input will be returned. + * @param {String} outputType the output type. + * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. + * @throws {Error} an Error if the browser doesn't support the requested output type. + */ +exports.transformTo = function(outputType, input) { + if (!input) { + // undefined, null, etc + // an empty string won't harm. + input = ""; + } + if (!outputType) { + return input; + } + exports.checkSupport(outputType); + var inputType = exports.getTypeOf(input); + var result = transform[inputType][outputType](input); + return result; +}; + +/** + * Return the type of the input. + * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. + * @param {Object} input the input to identify. + * @return {String} the (lowercase) type of the input. + */ +exports.getTypeOf = function(input) { + if (typeof input === "string") { + return "string"; + } + if (Object.prototype.toString.call(input) === "[object Array]") { + return "array"; + } + if (support.nodebuffer && nodejsUtils.isBuffer(input)) { + return "nodebuffer"; + } + if (support.uint8array && input instanceof Uint8Array) { + return "uint8array"; + } + if (support.arraybuffer && input instanceof ArrayBuffer) { + return "arraybuffer"; + } +}; + +/** + * Throw an exception if the type is not supported. + * @param {String} type the type to check. + * @throws {Error} an Error if the browser doesn't support the requested type. + */ +exports.checkSupport = function(type) { + var supported = support[type.toLowerCase()]; + if (!supported) { + throw new Error(type + " is not supported by this platform"); + } +}; + +exports.MAX_VALUE_16BITS = 65535; +exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 + +/** + * Prettify a string read as binary. + * @param {string} str the string to prettify. + * @return {string} a pretty string. + */ +exports.pretty = function(str) { + var res = '', + code, i; + for (i = 0; i < (str || "").length; i++) { + code = str.charCodeAt(i); + res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); + } + return res; +}; + +/** + * Defer the call of a function. + * @param {Function} callback the function to call asynchronously. + * @param {Array} args the arguments to give to the callback. + */ +exports.delay = function(callback, args, self) { + setImmediate(function () { + callback.apply(self || null, args || []); + }); +}; + +/** + * Extends a prototype with an other, without calling a constructor with + * side effects. Inspired by nodejs' `utils.inherits` + * @param {Function} ctor the constructor to augment + * @param {Function} superCtor the parent constructor to use + */ +exports.inherits = function (ctor, superCtor) { + var Obj = function() {}; + Obj.prototype = superCtor.prototype; + ctor.prototype = new Obj(); +}; + +/** + * Merge the objects passed as parameters into a new one. + * @private + * @param {...Object} var_args All objects to merge. + * @return {Object} a new object with the data of the others. + */ +exports.extend = function() { + var result = {}, i, attr; + for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers + for (attr in arguments[i]) { + if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { + result[attr] = arguments[i][attr]; + } + } + } + return result; +}; + +/** + * Transform arbitrary content into a Promise. + * @param {String} name a name for the content being processed. + * @param {Object} inputData the content to process. + * @param {Boolean} isBinary true if the content is not an unicode string + * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. + * @param {Boolean} isBase64 true if the string content is encoded with base64. + * @return {Promise} a promise in a format usable by JSZip. + */ +exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { + + // if inputData is already a promise, this flatten it. + var promise = external.Promise.resolve(inputData).then(function(data) { + + + var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); + + if (isBlob && typeof FileReader !== "undefined") { + return new external.Promise(function (resolve, reject) { + var reader = new FileReader(); + + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e.target.error); + }; + reader.readAsArrayBuffer(data); + }); + } else { + return data; + } + }); + + return promise.then(function(data) { + var dataType = exports.getTypeOf(data); + + if (!dataType) { + return external.Promise.reject( + new Error("Can't read the data of '" + name + "'. Is it " + + "in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") + ); + } + // special case : it's way easier to work with Uint8Array than with ArrayBuffer + if (dataType === "arraybuffer") { + data = exports.transformTo("uint8array", data); + } else if (dataType === "string") { + if (isBase64) { + data = base64.decode(data); + } + else if (isBinary) { + // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask + if (isOptimizedBinaryString !== true) { + // this is a string, not in a base64 format. + // Be sure that this is a correct "binary string" + data = string2binary(data); + } + } + } + return data; + }); +}; + +},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"core-js/library/fn/set-immediate":36}],33:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var sig = require('./signature'); +var ZipEntry = require('./zipEntry'); +var utf8 = require('./utf8'); +var support = require('./support'); +// class ZipEntries {{{ +/** + * All the entries in the zip file. + * @constructor + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntries(loadOptions) { + this.files = []; + this.loadOptions = loadOptions; +} +ZipEntries.prototype = { + /** + * Check that the reader is on the specified signature. + * @param {string} expectedSignature the expected signature. + * @throws {Error} if it is an other signature. + */ + checkSignature: function(expectedSignature) { + if (!this.reader.readAndCheckSignature(expectedSignature)) { + this.reader.index -= 4; + var signature = this.reader.readString(4); + throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); + } + }, + /** + * Check if the given signature is at the given index. + * @param {number} askedIndex the index to check. + * @param {string} expectedSignature the signature to expect. + * @return {boolean} true if the signature is here, false otherwise. + */ + isSignature: function(askedIndex, expectedSignature) { + var currentIndex = this.reader.index; + this.reader.setIndex(askedIndex); + var signature = this.reader.readString(4); + var result = signature === expectedSignature; + this.reader.setIndex(currentIndex); + return result; + }, + /** + * Read the end of the central directory. + */ + readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2); + this.diskWithCentralDirStart = this.reader.readInt(2); + this.centralDirRecordsOnThisDisk = this.reader.readInt(2); + this.centralDirRecords = this.reader.readInt(2); + this.centralDirSize = this.reader.readInt(4); + this.centralDirOffset = this.reader.readInt(4); + + this.zipCommentLength = this.reader.readInt(2); + // warning : the encoding depends of the system locale + // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. + // On a windows machine, this field is encoded with the localized windows code page. + var zipComment = this.reader.readData(this.zipCommentLength); + var decodeParamType = support.uint8array ? "uint8array" : "array"; + // To get consistent behavior with the generation part, we will assume that + // this is utf8 encoded unless specified otherwise. + var decodeContent = utils.transformTo(decodeParamType, zipComment); + this.zipComment = this.loadOptions.decodeFileName(decodeContent); + }, + /** + * Read the end of the Zip 64 central directory. + * Not merged with the method readEndOfCentral : + * The end of central can coexist with its Zip64 brother, + * I don't want to read the wrong number of bytes ! + */ + readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8); + this.reader.skip(4); + // this.versionMadeBy = this.reader.readString(2); + // this.versionNeeded = this.reader.readInt(2); + this.diskNumber = this.reader.readInt(4); + this.diskWithCentralDirStart = this.reader.readInt(4); + this.centralDirRecordsOnThisDisk = this.reader.readInt(8); + this.centralDirRecords = this.reader.readInt(8); + this.centralDirSize = this.reader.readInt(8); + this.centralDirOffset = this.reader.readInt(8); + + this.zip64ExtensibleData = {}; + var extraDataSize = this.zip64EndOfCentralSize - 44, + index = 0, + extraFieldId, + extraFieldLength, + extraFieldValue; + while (index < extraDataSize) { + extraFieldId = this.reader.readInt(2); + extraFieldLength = this.reader.readInt(4); + extraFieldValue = this.reader.readData(extraFieldLength); + this.zip64ExtensibleData[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Read the end of the Zip 64 central directory locator. + */ + readBlockZip64EndOfCentralLocator: function() { + this.diskWithZip64CentralDirStart = this.reader.readInt(4); + this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); + this.disksCount = this.reader.readInt(4); + if (this.disksCount > 1) { + throw new Error("Multi-volumes zip are not supported"); + } + }, + /** + * Read the local files, based on the offset read in the central part. + */ + readLocalFiles: function() { + var i, file; + for (i = 0; i < this.files.length; i++) { + file = this.files[i]; + this.reader.setIndex(file.localHeaderOffset); + this.checkSignature(sig.LOCAL_FILE_HEADER); + file.readLocalPart(this.reader); + file.handleUTF8(); + file.processAttributes(); + } + }, + /** + * Read the central directory. + */ + readCentralDir: function() { + var file; + + this.reader.setIndex(this.centralDirOffset); + while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) { + file = new ZipEntry({ + zip64: this.zip64 + }, this.loadOptions); + file.readCentralPart(this.reader); + this.files.push(file); + } + + if (this.centralDirRecords !== this.files.length) { + if (this.centralDirRecords !== 0 && this.files.length === 0) { + // We expected some records but couldn't find ANY. + // This is really suspicious, as if something went wrong. + throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); + } else { + // We found some records but not all. + // Something is wrong but we got something for the user: no error here. + // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length); + } + } + }, + /** + * Read the end of central directory. + */ + readEndOfCentral: function() { + var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); + if (offset < 0) { + // Check if the content is a truncated zip or complete garbage. + // A "LOCAL_FILE_HEADER" is not required at the beginning (auto + // extractible zip for example) but it can give a good hint. + // If an ajax request was used without responseType, we will also + // get unreadable data. + var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER); + + if (isGarbage) { + throw new Error("Can't find end of central directory : is this a zip file ? " + + "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"); + } else { + throw new Error("Corrupted zip: can't find end of central directory"); + } + + } + this.reader.setIndex(offset); + var endOfCentralDirOffset = offset; + this.checkSignature(sig.CENTRAL_DIRECTORY_END); + this.readBlockEndOfCentral(); + + + /* extract from the zip spec : + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + */ + if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { + this.zip64 = true; + + /* + Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from + the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents + all numbers as 64-bit double precision IEEE 754 floating point numbers. + So, we have 53bits for integers and bitwise operations treat everything as 32bits. + see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators + and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 + */ + + // should look for a zip64 EOCD locator + offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + if (offset < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + this.readBlockZip64EndOfCentralLocator(); + + // now the zip64 EOCD record + if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) { + // console.warn("ZIP64 end of central directory not where expected."); + this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + if (this.relativeOffsetEndOfZip64CentralDir < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); + } + } + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + this.readBlockZip64EndOfCentral(); + } + + var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize; + if (this.zip64) { + expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator + expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize; + } + + var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset; + + if (extraBytes > 0) { + // console.warn(extraBytes, "extra bytes at beginning or within zipfile"); + if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) { + // The offsets seem wrong, but we have something at the specified offset. + // So… we keep it. + } else { + // the offset is wrong, update the "zero" of the reader + // this happens if data has been prepended (crx files for example) + this.reader.zero = extraBytes; + } + } else if (extraBytes < 0) { + throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes."); + } + }, + prepareReader: function(data) { + this.reader = readerFor(data); + }, + /** + * Read a zip file and create ZipEntries. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. + */ + load: function(data) { + this.prepareReader(data); + this.readEndOfCentral(); + this.readCentralDir(); + this.readLocalFiles(); + } +}; +// }}} end of ZipEntries +module.exports = ZipEntries; + +},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var CompressedObject = require('./compressedObject'); +var crc32fn = require('./crc32'); +var utf8 = require('./utf8'); +var compressions = require('./compressions'); +var support = require('./support'); + +var MADE_BY_DOS = 0x00; +var MADE_BY_UNIX = 0x03; + +/** + * Find a compression registered in JSZip. + * @param {string} compressionMethod the method magic to find. + * @return {Object|null} the JSZip compression object, null if none found. + */ +var findCompression = function(compressionMethod) { + for (var method in compressions) { + if (!compressions.hasOwnProperty(method)) { + continue; + } + if (compressions[method].magic === compressionMethod) { + return compressions[method]; + } + } + return null; +}; + +// class ZipEntry {{{ +/** + * An entry in the zip file. + * @constructor + * @param {Object} options Options of the current file. + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntry(options, loadOptions) { + this.options = options; + this.loadOptions = loadOptions; +} +ZipEntry.prototype = { + /** + * say if the file is encrypted. + * @return {boolean} true if the file is encrypted, false otherwise. + */ + isEncrypted: function() { + // bit 1 is set + return (this.bitFlag & 0x0001) === 0x0001; + }, + /** + * say if the file has utf-8 filename/comment. + * @return {boolean} true if the filename/comment is in utf-8, false otherwise. + */ + useUTF8: function() { + // bit 11 is set + return (this.bitFlag & 0x0800) === 0x0800; + }, + /** + * Read the local part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readLocalPart: function(reader) { + var compression, localExtraFieldsLength; + + // we already know everything from the central dir ! + // If the central dir data are false, we are doomed. + // On the bright side, the local part is scary : zip64, data descriptors, both, etc. + // The less data we get here, the more reliable this should be. + // Let's skip the whole header and dash to the data ! + reader.skip(22); + // in some zip created on windows, the filename stored in the central dir contains \ instead of /. + // Strangely, the filename here is OK. + // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes + // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... + // Search "unzip mismatching "local" filename continuing with "central" filename version" on + // the internet. + // + // I think I see the logic here : the central directory is used to display + // content and the local directory is used to extract the files. Mixing / and \ + // may be used to display \ to windows users and use / when extracting the files. + // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 + this.fileNameLength = reader.readInt(2); + localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir + // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding. + this.fileName = reader.readData(this.fileNameLength); + reader.skip(localExtraFieldsLength); + + if (this.compressedSize === -1 || this.uncompressedSize === -1) { + throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)"); + } + + compression = findCompression(this.compressionMethod); + if (compression === null) { // no compression found + throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")"); + } + this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize)); + }, + + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readCentralPart: function(reader) { + this.versionMadeBy = reader.readInt(2); + reader.skip(2); + // this.versionNeeded = reader.readInt(2); + this.bitFlag = reader.readInt(2); + this.compressionMethod = reader.readString(2); + this.date = reader.readDate(); + this.crc32 = reader.readInt(4); + this.compressedSize = reader.readInt(4); + this.uncompressedSize = reader.readInt(4); + var fileNameLength = reader.readInt(2); + this.extraFieldsLength = reader.readInt(2); + this.fileCommentLength = reader.readInt(2); + this.diskNumberStart = reader.readInt(2); + this.internalFileAttributes = reader.readInt(2); + this.externalFileAttributes = reader.readInt(4); + this.localHeaderOffset = reader.readInt(4); + + if (this.isEncrypted()) { + throw new Error("Encrypted zip are not supported"); + } + + // will be read in the local part, see the comments there + reader.skip(fileNameLength); + this.readExtraFields(reader); + this.parseZIP64ExtraField(reader); + this.fileComment = reader.readData(this.fileCommentLength); + }, + + /** + * Parse the external file attributes and get the unix/dos permissions. + */ + processAttributes: function () { + this.unixPermissions = null; + this.dosPermissions = null; + var madeBy = this.versionMadeBy >> 8; + + // Check if we have the DOS directory flag set. + // We look for it in the DOS and UNIX permissions + // but some unknown platform could set it as a compatibility flag. + this.dir = this.externalFileAttributes & 0x0010 ? true : false; + + if(madeBy === MADE_BY_DOS) { + // first 6 bits (0 to 5) + this.dosPermissions = this.externalFileAttributes & 0x3F; + } + + if(madeBy === MADE_BY_UNIX) { + this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; + // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); + } + + // fail safe : if the name ends with a / it probably means a folder + if (!this.dir && this.fileNameStr.slice(-1) === '/') { + this.dir = true; + } + }, + + /** + * Parse the ZIP64 extra field and merge the info in the current ZipEntry. + * @param {DataReader} reader the reader to use. + */ + parseZIP64ExtraField: function(reader) { + + if (!this.extraFields[0x0001]) { + return; + } + + // should be something, preparing the extra reader + var extraReader = readerFor(this.extraFields[0x0001].value); + + // I really hope that these 64bits integer can fit in 32 bits integer, because js + // won't let us have more. + if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { + this.uncompressedSize = extraReader.readInt(8); + } + if (this.compressedSize === utils.MAX_VALUE_32BITS) { + this.compressedSize = extraReader.readInt(8); + } + if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { + this.localHeaderOffset = extraReader.readInt(8); + } + if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { + this.diskNumberStart = extraReader.readInt(4); + } + }, + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readExtraFields: function(reader) { + var end = reader.index + this.extraFieldsLength, + extraFieldId, + extraFieldLength, + extraFieldValue; + + if (!this.extraFields) { + this.extraFields = {}; + } + + while (reader.index < end) { + extraFieldId = reader.readInt(2); + extraFieldLength = reader.readInt(2); + extraFieldValue = reader.readData(extraFieldLength); + + this.extraFields[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Apply an UTF8 transformation if needed. + */ + handleUTF8: function() { + var decodeParamType = support.uint8array ? "uint8array" : "array"; + if (this.useUTF8()) { + this.fileNameStr = utf8.utf8decode(this.fileName); + this.fileCommentStr = utf8.utf8decode(this.fileComment); + } else { + var upath = this.findExtraFieldUnicodePath(); + if (upath !== null) { + this.fileNameStr = upath; + } else { + // ASCII text or unsupported code page + var fileNameByteArray = utils.transformTo(decodeParamType, this.fileName); + this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray); + } + + var ucomment = this.findExtraFieldUnicodeComment(); + if (ucomment !== null) { + this.fileCommentStr = ucomment; + } else { + // ASCII text or unsupported code page + var commentByteArray = utils.transformTo(decodeParamType, this.fileComment); + this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray); + } + } + }, + + /** + * Find the unicode path declared in the extra field, if any. + * @return {String} the unicode path, null otherwise. + */ + findExtraFieldUnicodePath: function() { + var upathField = this.extraFields[0x7075]; + if (upathField) { + var extraReader = readerFor(upathField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the filename changed, this field is out of date. + if (crc32fn(this.fileName) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(upathField.length - 5)); + } + return null; + }, + + /** + * Find the unicode comment declared in the extra field, if any. + * @return {String} the unicode comment, null otherwise. + */ + findExtraFieldUnicodeComment: function() { + var ucommentField = this.extraFields[0x6375]; + if (ucommentField) { + var extraReader = readerFor(ucommentField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the comment changed, this field is out of date. + if (crc32fn(this.fileComment) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(ucommentField.length - 5)); + } + return null; + } +}; +module.exports = ZipEntry; + +},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(require,module,exports){ +'use strict'; + +var StreamHelper = require('./stream/StreamHelper'); +var DataWorker = require('./stream/DataWorker'); +var utf8 = require('./utf8'); +var CompressedObject = require('./compressedObject'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * A simple object representing a file in the zip file. + * @constructor + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data + * @param {Object} options the options of the file + */ +var ZipObject = function(name, data, options) { + this.name = name; + this.dir = options.dir; + this.date = options.date; + this.comment = options.comment; + this.unixPermissions = options.unixPermissions; + this.dosPermissions = options.dosPermissions; + + this._data = data; + this._dataBinary = options.binary; + // keep only the compression + this.options = { + compression : options.compression, + compressionOptions : options.compressionOptions + }; +}; + +ZipObject.prototype = { + /** + * Create an internal stream for the content of this object. + * @param {String} type the type of each chunk. + * @return StreamHelper the stream. + */ + internalStream: function (type) { + var result = null, outputType = "string"; + try { + if (!type) { + throw new Error("No output type specified."); + } + outputType = type.toLowerCase(); + var askUnicodeString = outputType === "string" || outputType === "text"; + if (outputType === "binarystring" || outputType === "text") { + outputType = "string"; + } + result = this._decompressWorker(); + + var isUnicodeString = !this._dataBinary; + + if (isUnicodeString && !askUnicodeString) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + if (!isUnicodeString && askUnicodeString) { + result = result.pipe(new utf8.Utf8DecodeWorker()); + } + } catch (e) { + result = new GenericWorker("error"); + result.error(e); + } + + return new StreamHelper(result, outputType, ""); + }, + + /** + * Prepare the content in the asked type. + * @param {String} type the type of the result. + * @param {Function} onUpdate a function to call on each internal update. + * @return Promise the promise of the result. + */ + async: function (type, onUpdate) { + return this.internalStream(type).accumulate(onUpdate); + }, + + /** + * Prepare the content as a nodejs stream. + * @param {String} type the type of each chunk. + * @param {Function} onUpdate a function to call on each internal update. + * @return Stream the stream. + */ + nodeStream: function (type, onUpdate) { + return this.internalStream(type || "nodebuffer").toNodejsStream(onUpdate); + }, + + /** + * Return a worker for the compressed content. + * @private + * @param {Object} compression the compression object to use. + * @param {Object} compressionOptions the options to use when compressing. + * @return Worker the worker. + */ + _compressWorker: function (compression, compressionOptions) { + if ( + this._data instanceof CompressedObject && + this._data.compression.magic === compression.magic + ) { + return this._data.getCompressedWorker(); + } else { + var result = this._decompressWorker(); + if(!this._dataBinary) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + return CompressedObject.createWorkerFrom(result, compression, compressionOptions); + } + }, + /** + * Return a worker for the decompressed content. + * @private + * @return Worker the worker. + */ + _decompressWorker : function () { + if (this._data instanceof CompressedObject) { + return this._data.getContentWorker(); + } else if (this._data instanceof GenericWorker) { + return this._data; + } else { + return new DataWorker(this._data); + } + } +}; + +var removedMethods = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"]; +var removedFn = function () { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); +}; + +for(var i = 0; i < removedMethods.length; i++) { + ZipObject.prototype[removedMethods[i]] = removedFn; +} +module.exports = ZipObject; + +},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(require,module,exports){ +require('../modules/web.immediate'); +module.exports = require('../modules/_core').setImmediate; +},{"../modules/_core":40,"../modules/web.immediate":56}],37:[function(require,module,exports){ +module.exports = function(it){ + if(typeof it != 'function')throw TypeError(it + ' is not a function!'); + return it; +}; +},{}],38:[function(require,module,exports){ +var isObject = require('./_is-object'); +module.exports = function(it){ + if(!isObject(it))throw TypeError(it + ' is not an object!'); + return it; +}; +},{"./_is-object":51}],39:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = function(it){ + return toString.call(it).slice(8, -1); +}; +},{}],40:[function(require,module,exports){ +var core = module.exports = {version: '2.3.0'}; +if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef +},{}],41:[function(require,module,exports){ +// optional / simple context binding +var aFunction = require('./_a-function'); +module.exports = function(fn, that, length){ + aFunction(fn); + if(that === undefined)return fn; + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; +}; +},{"./_a-function":37}],42:[function(require,module,exports){ +// Thank's IE8 for his funny defineProperty +module.exports = !require('./_fails')(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_fails":45}],43:[function(require,module,exports){ +var isObject = require('./_is-object') + , document = require('./_global').document + // in old IE typeof document.createElement is 'object' + , is = isObject(document) && isObject(document.createElement); +module.exports = function(it){ + return is ? document.createElement(it) : {}; +}; +},{"./_global":46,"./_is-object":51}],44:[function(require,module,exports){ +var global = require('./_global') + , core = require('./_core') + , ctx = require('./_ctx') + , hide = require('./_hide') + , PROTOTYPE = 'prototype'; + +var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , IS_WRAP = type & $export.W + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] + , key, own, out; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if(own && key in exports)continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function(C){ + var F = function(a, b, c){ + if(this instanceof C){ + switch(arguments.length){ + case 0: return new C; + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if(IS_PROTO){ + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); + } + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; +},{"./_core":40,"./_ctx":41,"./_global":46,"./_hide":47}],45:[function(require,module,exports){ +module.exports = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } +}; +},{}],46:[function(require,module,exports){ +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); +if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef +},{}],47:[function(require,module,exports){ +var dP = require('./_object-dp') + , createDesc = require('./_property-desc'); +module.exports = require('./_descriptors') ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); +} : function(object, key, value){ + object[key] = value; + return object; +}; +},{"./_descriptors":42,"./_object-dp":52,"./_property-desc":53}],48:[function(require,module,exports){ +module.exports = require('./_global').document && document.documentElement; +},{"./_global":46}],49:[function(require,module,exports){ +module.exports = !require('./_descriptors') && !require('./_fails')(function(){ + return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_descriptors":42,"./_dom-create":43,"./_fails":45}],50:[function(require,module,exports){ +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function(fn, args, that){ + var un = that === undefined; + switch(args.length){ + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; +},{}],51:[function(require,module,exports){ +module.exports = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; +},{}],52:[function(require,module,exports){ +var anObject = require('./_an-object') + , IE8_DOM_DEFINE = require('./_ie8-dom-define') + , toPrimitive = require('./_to-primitive') + , dP = Object.defineProperty; + +exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){ + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if(IE8_DOM_DEFINE)try { + return dP(O, P, Attributes); + } catch(e){ /* empty */ } + if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); + if('value' in Attributes)O[P] = Attributes.value; + return O; +}; +},{"./_an-object":38,"./_descriptors":42,"./_ie8-dom-define":49,"./_to-primitive":55}],53:[function(require,module,exports){ +module.exports = function(bitmap, value){ + return { + enumerable : !(bitmap & 1), + configurable: !(bitmap & 2), + writable : !(bitmap & 4), + value : value + }; +}; +},{}],54:[function(require,module,exports){ +var ctx = require('./_ctx') + , invoke = require('./_invoke') + , html = require('./_html') + , cel = require('./_dom-create') + , global = require('./_global') + , process = global.process + , setTask = global.setImmediate + , clearTask = global.clearImmediate + , MessageChannel = global.MessageChannel + , counter = 0 + , queue = {} + , ONREADYSTATECHANGE = 'onreadystatechange' + , defer, channel, port; +var run = function(){ + var id = +this; + if(queue.hasOwnProperty(id)){ + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function(event){ + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if(!setTask || !clearTask){ + setTask = function setImmediate(fn){ + var args = [], i = 1; + while(arguments.length > i)args.push(arguments[i++]); + queue[++counter] = function(){ + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id){ + delete queue[id]; + }; + // Node.js 0.8- + if(require('./_cof')(process) == 'process'){ + defer = function(id){ + process.nextTick(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if(MessageChannel){ + channel = new MessageChannel; + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ + defer = function(id){ + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if(ONREADYSTATECHANGE in cel('script')){ + defer = function(id){ + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function(id){ + setTimeout(ctx(run, id, 1), 0); + }; + } +} +module.exports = { + set: setTask, + clear: clearTask +}; +},{"./_cof":39,"./_ctx":41,"./_dom-create":43,"./_global":46,"./_html":48,"./_invoke":50}],55:[function(require,module,exports){ +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = require('./_is-object'); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function(it, S){ + if(!isObject(it))return it; + var fn, val; + if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; + if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + throw TypeError("Can't convert object to primitive value"); +}; +},{"./_is-object":51}],56:[function(require,module,exports){ +var $export = require('./_export') + , $task = require('./_task'); +$export($export.G + $export.B, { + setImmediate: $task.set, + clearImmediate: $task.clear +}); +},{"./_export":44,"./_task":54}],57:[function(require,module,exports){ +(function (global){ +'use strict'; +var Mutation = global.MutationObserver || global.WebKitMutationObserver; + +var scheduleDrain; + +{ + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + scheduleDrain = function () { + element.data = (called = ++called % 2); + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + + // Create a + + - - +
                - -
                - - - - - - - -
                - - -
                -

                ACF (Core) 0.5.0-SNAPSHOT API

                -
                -
                - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                Packages 
                PackageDescription
                co.aikar.commands 
                co.aikar.commands.annotation 
                co.aikar.commands.apachecommonslang 
                co.aikar.commands.contexts 
                co.aikar.commands.processors 
                -
                - -
                - - - - - - - -
                - - -

                Copyright © 2019. All rights reserved.

                +

                index.html

                +
                diff --git a/docs/acf-core/overview-tree.html b/docs/acf-core/overview-tree.html index 3a328085..31bde0fd 100644 --- a/docs/acf-core/overview-tree.html +++ b/docs/acf-core/overview-tree.html @@ -1,12 +1,21 @@ - + - Class Hierarchy (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Hierarchy For All Packages

                Package Hierarchies: @@ -80,51 +104,52 @@
              +

              Class Hierarchy

              +

              Interface Hierarchy

              +
              +

              Annotation Type Hierarchy

              +
              +

              Enum Hierarchy

              +
              +
              + diff --git a/docs/acf-core/package-search-index.js b/docs/acf-core/package-search-index.js new file mode 100644 index 00000000..577aa448 --- /dev/null +++ b/docs/acf-core/package-search-index.js @@ -0,0 +1 @@ +packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"co.aikar.commands"},{"l":"co.aikar.commands.annotation"},{"l":"co.aikar.commands.apachecommonslang"},{"l":"co.aikar.commands.contexts"},{"l":"co.aikar.commands.processors"}] \ No newline at end of file diff --git a/docs/acf-core/package-search-index.zip b/docs/acf-core/package-search-index.zip new file mode 100644 index 00000000..dda9d201 Binary files /dev/null and b/docs/acf-core/package-search-index.zip differ diff --git a/docs/acf-core/resources/glass.png b/docs/acf-core/resources/glass.png new file mode 100644 index 00000000..a7f591f4 Binary files /dev/null and b/docs/acf-core/resources/glass.png differ diff --git a/docs/acf-core/resources/x.png b/docs/acf-core/resources/x.png new file mode 100644 index 00000000..30548a75 Binary files /dev/null and b/docs/acf-core/resources/x.png differ diff --git a/docs/acf-core/script.js b/docs/acf-core/script.js index b3463569..0eaaf535 100644 --- a/docs/acf-core/script.js +++ b/docs/acf-core/script.js @@ -1,9 +1,114 @@ -function show(type) -{ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var moduleSearchIndex; +var packageSearchIndex; +var typeSearchIndex; +var memberSearchIndex; +var tagSearchIndex; +function loadScripts(doc, tag) { + createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); + if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || + window.navigator.userAgent.indexOf('Edge/') > 0) { + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); + } + createElem(doc, tag, 'search.js'); + + $.get(pathtoroot + "module-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + moduleSearchIndex = JSON.parse(zip.file("module-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "package-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + packageSearchIndex = JSON.parse(zip.file("package-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "type-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + typeSearchIndex = JSON.parse(zip.file("type-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "member-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + memberSearchIndex = JSON.parse(zip.file("member-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "tag-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + tagSearchIndex = JSON.parse(zip.file("tag-search-index.json").asText()); + }); + }); + if (!moduleSearchIndex) { + createElem(doc, tag, 'module-search-index.js'); + } + if (!packageSearchIndex) { + createElem(doc, tag, 'package-search-index.js'); + } + if (!typeSearchIndex) { + createElem(doc, tag, 'type-search-index.js'); + } + if (!memberSearchIndex) { + createElem(doc, tag, 'member-search-index.js'); + } + if (!tagSearchIndex) { + createElem(doc, tag, 'tag-search-index.js'); + } + $(window).resize(function() { + $('.navPadding').css('padding-top', $('.fixedNav').css("height")); + }); +} + +function createElem(doc, tag, path) { + var script = doc.createElement(tag); + var scriptElement = doc.getElementsByTagName(tag)[0]; + script.src = pathtoroot + path; + scriptElement.parentNode.insertBefore(script, scriptElement); +} + +function show(type) { count = 0; - for (var key in methods) { + for (var key in data) { var row = document.getElementById(key); - if ((methods[key] & type) != 0) { + if ((data[key] & type) !== 0) { row.style.display = ''; row.className = (count++ % 2) ? rowColor : altColor; } @@ -13,8 +118,7 @@ function show(type) updateTabs(type); } -function updateTabs(type) -{ +function updateTabs(type) { for (var value in tabs) { var sNode = document.getElementById(tabs[value][0]); var spanNode = sNode.firstChild; @@ -28,3 +132,8 @@ function updateTabs(type) } } } + +function updateModuleFrame(pFrame, cFrame) { + top.packageFrame.location = pFrame; + top.classFrame.location = cFrame; +} diff --git a/docs/acf-core/search.js b/docs/acf-core/search.js new file mode 100644 index 00000000..b773531b --- /dev/null +++ b/docs/acf-core/search.js @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var noResult = {l: "No results found"}; +var catModules = "Modules"; +var catPackages = "Packages"; +var catTypes = "Types"; +var catMembers = "Members"; +var catSearchTags = "SearchTags"; +var highlight = "$&"; +var camelCaseRegexp = ""; +var secondaryMatcher = ""; +function getHighlightedText(item) { + var ccMatcher = new RegExp(camelCaseRegexp); + var label = item.replace(ccMatcher, highlight); + if (label === item) { + label = item.replace(secondaryMatcher, highlight); + } + return label; +} +function getURLPrefix(ui) { + var urlPrefix=""; + if (useModuleDirectories) { + var slash = "/"; + if (ui.item.category === catModules) { + return ui.item.l + slash; + } else if (ui.item.category === catPackages && ui.item.m) { + return ui.item.m + slash; + } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { + $.each(packageSearchIndex, function(index, item) { + if (ui.item.p == item.l) { + urlPrefix = item.m + slash; + } + }); + return urlPrefix; + } else { + return urlPrefix; + } + } + return urlPrefix; +} +var watermark = 'Search'; +$(function() { + $("#search").val(''); + $("#search").prop("disabled", false); + $("#reset").prop("disabled", false); + $("#search").val(watermark).addClass('watermark'); + $("#search").blur(function() { + if ($(this).val().length == 0) { + $(this).val(watermark).addClass('watermark'); + } + }); + $("#search").on('click keydown', function() { + if ($(this).val() == watermark) { + $(this).val('').removeClass('watermark'); + } + }); + $("#reset").click(function() { + $("#search").val(''); + $("#search").focus(); + }); + $("#search").focus(); + $("#search")[0].setSelectionRange(0, 0); +}); +$.widget("custom.catcomplete", $.ui.autocomplete, { + _create: function() { + this._super(); + this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)"); + }, + _renderMenu: function(ul, items) { + var rMenu = this, + currentCategory = ""; + rMenu.menu.bindings = $(); + $.each(items, function(index, item) { + var li; + if (item.l !== noResult.l && item.category !== currentCategory) { + ul.append("
            • " + item.category + "
            • "); + currentCategory = item.category; + } + li = rMenu._renderItemData(ul, item); + if (item.category) { + li.attr("aria-label", item.category + " : " + item.l); + li.attr("class", "resultItem"); + } else { + li.attr("aria-label", item.l); + li.attr("class", "resultItem"); + } + }); + }, + _renderItem: function(ul, item) { + var label = ""; + if (item.category === catModules) { + label = getHighlightedText(item.l); + } else if (item.category === catPackages) { + label = (item.m) + ? getHighlightedText(item.m + "/" + item.l) + : getHighlightedText(item.l); + } else if (item.category === catTypes) { + label = (item.p) + ? getHighlightedText(item.p + "." + item.l) + : getHighlightedText(item.l); + } else if (item.category === catMembers) { + label = getHighlightedText(item.p + "." + (item.c + "." + item.l)); + } else if (item.category === catSearchTags) { + label = getHighlightedText(item.l); + } else { + label = item.l; + } + var li = $("
            • ").appendTo(ul); + var div = $("
              ").appendTo(li); + if (item.category === catSearchTags) { + if (item.d) { + div.html(label + " (" + item.h + ")
              " + + item.d + "
              "); + } else { + div.html(label + " (" + item.h + ")"); + } + } else { + div.html(label); + } + return li; + } +}); +$(function() { + $("#search").catcomplete({ + minLength: 1, + delay: 100, + source: function(request, response) { + var result = new Array(); + var presult = new Array(); + var tresult = new Array(); + var mresult = new Array(); + var tgresult = new Array(); + var secondaryresult = new Array(); + var displayCount = 0; + var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i"); + camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)"); + var camelCaseMatcher = new RegExp("^" + camelCaseRegexp); + secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); + + // Return the nested innermost name from the specified object + function nestedName(e) { + return e.l.substring(e.l.lastIndexOf(".") + 1); + } + + function concatResults(a1, a2) { + a1 = a1.concat(a2); + a2.length = 0; + return a1; + } + + if (moduleSearchIndex) { + var mdleCount = 0; + $.each(moduleSearchIndex, function(index, item) { + item.category = catModules; + if (exactMatcher.test(item.l)) { + result.push(item); + mdleCount++; + } else if (camelCaseMatcher.test(item.l)) { + result.push(item); + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + displayCount = mdleCount; + result = concatResults(result, secondaryresult); + } + if (packageSearchIndex) { + var pCount = 0; + var pkg = ""; + $.each(packageSearchIndex, function(index, item) { + item.category = catPackages; + pkg = (item.m) + ? (item.m + "/" + item.l) + : item.l; + if (exactMatcher.test(item.l)) { + presult.push(item); + pCount++; + } else if (camelCaseMatcher.test(pkg)) { + presult.push(item); + } else if (secondaryMatcher.test(pkg)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(presult, secondaryresult)); + displayCount = (pCount > displayCount) ? pCount : displayCount; + } + if (typeSearchIndex) { + var tCount = 0; + $.each(typeSearchIndex, function(index, item) { + item.category = catTypes; + var s = nestedName(item); + if (exactMatcher.test(s)) { + tresult.push(item); + tCount++; + } else if (camelCaseMatcher.test(s)) { + tresult.push(item); + } else if (secondaryMatcher.test(item.p + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tresult, secondaryresult)); + displayCount = (tCount > displayCount) ? tCount : displayCount; + } + if (memberSearchIndex) { + var mCount = 0; + $.each(memberSearchIndex, function(index, item) { + item.category = catMembers; + var s = nestedName(item); + if (exactMatcher.test(s)) { + mresult.push(item); + mCount++; + } else if (camelCaseMatcher.test(s)) { + mresult.push(item); + } else if (secondaryMatcher.test(item.c + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(mresult, secondaryresult)); + displayCount = (mCount > displayCount) ? mCount : displayCount; + } + if (tagSearchIndex) { + var tgCount = 0; + $.each(tagSearchIndex, function(index, item) { + item.category = catSearchTags; + if (exactMatcher.test(item.l)) { + tgresult.push(item); + tgCount++; + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tgresult, secondaryresult)); + displayCount = (tgCount > displayCount) ? tgCount : displayCount; + } + displayCount = (displayCount > 500) ? displayCount : 500; + var counter = function() { + var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0}; + var f = function(item) { + count[item.category] += 1; + return (count[item.category] <= displayCount); + }; + return f; + }(); + response(result.filter(counter)); + }, + response: function(event, ui) { + if (!ui.content.length) { + ui.content.push(noResult); + } else { + $("#search").empty(); + } + }, + autoFocus: true, + position: { + collision: "flip" + }, + select: function(event, ui) { + if (ui.item.l !== noResult.l) { + var url = getURLPrefix(ui); + if (ui.item.category === catModules) { + if (useModuleDirectories) { + url += "module-summary.html"; + } else { + url = ui.item.l + "-summary.html"; + } + } else if (ui.item.category === catPackages) { + if (ui.item.url) { + url = ui.item.url; + } else { + url += ui.item.l.replace(/\./g, '/') + "/package-summary.html"; + } + } else if (ui.item.category === catTypes) { + if (ui.item.url) { + url = ui.item.url; + } else if (ui.item.p === "") { + url += ui.item.l + ".html"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; + } + } else if (ui.item.category === catMembers) { + if (ui.item.p === "") { + url += ui.item.c + ".html" + "#"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; + } + if (ui.item.url) { + url += ui.item.url; + } else { + url += ui.item.l; + } + } else if (ui.item.category === catSearchTags) { + url += ui.item.u; + } + if (top !== window) { + parent.classFrame.location = pathtoroot + url; + } else { + window.location.href = pathtoroot + url; + } + $("#search").focus(); + } + } + }); +}); diff --git a/docs/acf-core/serialized-form.html b/docs/acf-core/serialized-form.html index 434e8b15..b8c590f5 100644 --- a/docs/acf-core/serialized-form.html +++ b/docs/acf-core/serialized-form.html @@ -1,12 +1,21 @@ - + - Serialized Form (ACF (Core) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Serialized Form

              +
            • + + diff --git a/docs/acf-core/src-html/co/aikar/commands/ACFUtil.html b/docs/acf-core/src-html/co/aikar/commands/ACFUtil.html index 6894e377..30b4d546 100644 --- a/docs/acf-core/src-html/co/aikar/commands/ACFUtil.html +++ b/docs/acf-core/src-html/co/aikar/commands/ACFUtil.html @@ -1,680 +1,682 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026
              -027import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              -028import org.jetbrains.annotations.Nullable;
              -029
              -030import java.math.BigDecimal;
              -031import java.text.Normalizer;
              -032import java.text.Normalizer.Form;
              -033import java.text.NumberFormat;
              -034import java.util.ArrayList;
              -035import java.util.Collection;
              -036import java.util.Iterator;
              -037import java.util.List;
              -038import java.util.Random;
              -039import java.util.function.Consumer;
              -040import java.util.regex.Matcher;
              -041import java.util.regex.Pattern;
              -042import java.util.stream.Collectors;
              -043import java.util.stream.Stream;
              -044
              -045@SuppressWarnings({"WeakerAccess", "unused"})
              -046public final class ACFUtil {
              -047
              -048    public static final Random RANDOM = new Random();
              -049
              -050    private ACFUtil() {
              -051    }
              -052
              -053    public static String padRight(String s, int n) {
              -054        return String.format("%1$-" + n + "s", s);
              -055    }
              -056
              -057    public static String padLeft(String s, int n) {
              -058        return String.format("%1$" + n + "s", s);
              -059    }
              -060
              -061    public static String formatNumber(Integer balance) {
              -062        return NumberFormat.getInstance().format(balance);
              -063    }
              -064
              -065    public static <T extends Enum> T getEnumFromName(T[] types, String name) {
              -066        return getEnumFromName(types, name, null);
              -067    }
              -068
              -069    public static <T extends Enum> T getEnumFromName(T[] types, String name, T def) {
              -070        for (T type : types) {
              -071            if (type.name().equalsIgnoreCase(name)) {
              -072                return type;
              -073            }
              -074        }
              -075        return def;
              -076    }
              -077
              -078    public static <T extends Enum> T getEnumFromOrdinal(T[] types, int ordinal) {
              -079        for (T type : types) {
              -080            if (type.ordinal() == ordinal) {
              -081                return type;
              -082            }
              -083        }
              -084        return null;
              -085    }
              -086
              -087    public static String ucfirst(String str) {
              -088        return ApacheCommonsLangUtil.capitalizeFully(str);
              -089    }
              -090
              -091    public static Double parseDouble(String var) {
              -092        return parseDouble(var, null);
              -093    }
              -094
              -095    public static Double parseDouble(String var, Double def) {
              -096        if (var == null) {
              -097            return def;
              -098        }
              -099        try {
              -100            return Double.parseDouble(var);
              -101        } catch (NumberFormatException ignored) {
              -102        }
              -103        return def;
              -104    }
              -105
              -106    public static Float parseFloat(String var) {
              -107        return parseFloat(var, null);
              -108    }
              -109
              -110    public static Float parseFloat(String var, Float def) {
              -111        if (var == null) {
              -112            return def;
              -113        }
              -114        try {
              -115            return Float.parseFloat(var);
              -116        } catch (NumberFormatException ignored) {
              -117        }
              -118        return def;
              -119    }
              -120
              -121    public static Long parseLong(String var) {
              -122        return parseLong(var, null);
              -123    }
              -124
              -125    public static Long parseLong(String var, Long def) {
              -126        if (var == null) {
              -127            return def;
              -128        }
              -129        try {
              -130            return Long.parseLong(var);
              -131        } catch (NumberFormatException ignored) {
              -132        }
              -133        return def;
              -134    }
              -135
              -136    public static Integer parseInt(String var) {
              -137        return parseInt(var, null);
              -138    }
              -139
              -140    public static Integer parseInt(String var, Integer def) {
              -141        if (var == null) {
              -142            return def;
              -143        }
              -144        try {
              -145            return Integer.parseInt(var);
              -146        } catch (NumberFormatException ignored) {
              -147        }
              -148        return def;
              -149    }
              -150
              -151    public static boolean randBool() {
              -152        return RANDOM.nextBoolean();
              -153    }
              -154
              -155    public static <T> T nullDefault(Object val, Object def) {
              -156        //noinspection unchecked
              -157        return (T) (val != null ? val : def);
              -158    }
              -159
              -160    public static String join(Collection<String> args) {
              -161        return ApacheCommonsLangUtil.join(args, " ");
              -162    }
              -163
              -164    public static String join(Collection<String> args, String sep) {
              -165        return ApacheCommonsLangUtil.join(args, sep);
              -166    }
              -167
              -168    public static String join(String[] args) {
              -169        return join(args, 0, ' ');
              -170    }
              -171
              -172    public static String join(String[] args, String sep) {
              -173        return ApacheCommonsLangUtil.join(args, sep);
              -174    }
              -175
              -176    public static String join(String[] args, char sep) {
              -177        return join(args, 0, sep);
              -178    }
              -179
              -180    public static String join(String[] args, int index) {
              -181        return join(args, index, ' ');
              -182    }
              -183
              -184    public static String join(String[] args, int index, char sep) {
              -185        return ApacheCommonsLangUtil.join(args, sep, index, args.length);
              -186    }
              -187
              -188    public static String simplifyString(String str) {
              -189        if (str == null) {
              -190            return null;
              -191        }
              -192        return ACFPatterns.NON_ALPHA_NUMERIC.matcher(str.toLowerCase()).replaceAll("");
              -193    }
              -194
              -195    public static double round(double x, int scale) {
              -196        try {
              -197            return (new BigDecimal
              -198                    (Double.toString(x))
              -199                    .setScale(scale, BigDecimal.ROUND_HALF_UP))
              -200                    .doubleValue();
              -201        } catch (NumberFormatException ex) {
              -202            if (Double.isInfinite(x)) {
              -203                return x;
              -204            } else {
              -205                return Double.NaN;
              -206            }
              -207        }
              -208    }
              -209
              -210    public static int roundUp(int num, int multiple) {
              -211        if (multiple == 0) {
              -212            return num;
              -213        }
              -214
              -215        int remainder = num % multiple;
              -216        if (remainder == 0) {
              -217            return num;
              -218        }
              -219        return num + multiple - remainder;
              -220
              -221    }
              -222
              -223    public static String limit(String str, int limit) {
              -224        return str.length() > limit ? str.substring(0, limit) : str;
              -225    }
              -226
              -227    /**
              -228     * Plain string replacement, escapes replace value.
              -229     *
              -230     * @param string
              -231     * @param pattern
              -232     * @param repl
              -233     * @return
              -234     */
              -235    public static String replace(String string, Pattern pattern, String repl) {
              -236        return pattern.matcher(string).replaceAll(Matcher.quoteReplacement(repl));
              -237    }
              -238
              -239    /**
              -240     * Regex version of {@link #replace(String, Pattern, String)}
              -241     *
              -242     * @param string
              -243     * @param pattern
              -244     * @param repl
              -245     * @return
              -246     */
              -247    public static String replacePattern(String string, Pattern pattern, String repl) {
              -248        return pattern.matcher(string).replaceAll(repl);
              -249    }
              -250
              -251    /**
              -252     * Plain String replacement. If you need regex patterns, see {@link #replacePattern(String, String, String)}
              -253     *
              -254     * @param string
              -255     * @param pattern
              -256     * @param repl
              -257     * @return
              -258     */
              -259    public static String replace(String string, String pattern, String repl) {
              -260        return replace(string, ACFPatterns.getPattern(Pattern.quote(pattern)), repl);
              -261    }
              -262
              -263    /**
              -264     * Regex version of {@link #replace(String, String, String)}
              -265     *
              -266     * @param string
              -267     * @param pattern
              -268     * @param repl
              -269     * @return
              -270     */
              -271    public static String replacePattern(String string, String pattern, String repl) {
              -272        return replace(string, ACFPatterns.getPattern(pattern), repl);
              -273    }
              -274
              -275    /**
              -276     * Pure Regex Pattern matching and replacement, no escaping
              -277     *
              -278     * @param string
              -279     * @param pattern
              -280     * @param repl
              -281     * @return
              -282     */
              -283    public static String replacePatternMatch(String string, Pattern pattern, String repl) {
              -284        return pattern.matcher(string).replaceAll(repl);
              -285    }
              -286
              -287    /**
              -288     * Pure Regex Pattern matching and replacement, no escaping
              -289     *
              -290     * @param string
              -291     * @param pattern
              -292     * @param repl
              -293     * @return
              -294     */
              -295    public static String replacePatternMatch(String string, String pattern, String repl) {
              -296        return replacePatternMatch(string, ACFPatterns.getPattern(pattern), repl);
              -297    }
              -298
              -299    public static String replaceStrings(String string, String... replacements) {
              -300        if (replacements.length < 2 || replacements.length % 2 != 0) {
              -301            throw new IllegalArgumentException("Invalid Replacements");
              -302        }
              -303        for (int i = 0; i < replacements.length; i += 2) {
              -304            String key = replacements[i];
              -305            String value = replacements[i + 1];
              -306            if (value == null) value = "";
              -307            string = replace(string, key, value);
              -308        }
              -309        return string;
              -310    }
              -311
              -312    public static String replacePatterns(String string, String... replacements) {
              -313        if (replacements.length < 2 || replacements.length % 2 != 0) {
              -314            throw new IllegalArgumentException("Invalid Replacements");
              -315        }
              -316        for (int i = 0; i < replacements.length; i += 2) {
              -317            String key = replacements[i];
              -318            String value = replacements[i + 1];
              -319            if (value == null) value = "";
              -320            string = replacePattern(string, key, value);
              -321        }
              -322        return string;
              -323    }
              -324
              -325    public static String capitalize(String str, char[] delimiters) {
              -326        return ApacheCommonsLangUtil.capitalize(str, delimiters);
              -327    }
              -328
              -329    private static boolean isDelimiter(char ch, char[] delimiters) {
              -330        return ApacheCommonsLangUtil.isDelimiter(ch, delimiters);
              -331    }
              -332
              -333    public static <T> T random(List<T> arr) {
              -334        if (arr == null || arr.isEmpty()) {
              -335            return null;
              -336        }
              -337        return arr.get(RANDOM.nextInt(arr.size()));
              -338    }
              -339
              -340    public static <T> T random(T[] arr) {
              -341        if (arr == null || arr.length == 0) {
              -342            return null;
              -343        }
              -344        return arr[RANDOM.nextInt(arr.length)];
              -345    }
              -346
              -347    /**
              -348     * Added as im sure we will try to "Find this" again. This is no different than Enum.values() passed to above method logically
              -349     * but the array version is slightly faster.
              -350     *
              -351     * @param enm
              -352     * @param <T>
              -353     * @return
              -354     */
              -355    @Deprecated
              -356    public static <T extends Enum<?>> T random(Class<? extends T> enm) {
              -357        return random(enm.getEnumConstants());
              -358    }
              -359
              -360    public static String normalize(String s) {
              -361        if (s == null) {
              -362            return null;
              -363        }
              -364        return ACFPatterns.NON_PRINTABLE_CHARACTERS.matcher(Normalizer.normalize(s, Form.NFD)).replaceAll("");
              -365    }
              -366
              -367    public static int indexOf(String arg, String[] split) {
              -368        for (int i = 0; i < split.length; i++) {
              -369            if (arg == null) {
              -370                if (split[i] == null) {
              -371                    return i;
              -372                }
              -373            } else if (arg.equals(split[i])) {
              -374                return i;
              -375            }
              -376        }
              -377        return -1;
              -378    }
              -379
              -380    public static String capitalizeFirst(String name) {
              -381        return capitalizeFirst(name, '_');
              -382    }
              -383
              -384    public static String capitalizeFirst(String name, char separator) {
              -385        name = name.toLowerCase();
              -386        String[] split = name.split(Character.toString(separator));
              -387        StringBuilder total = new StringBuilder(3);
              -388        for (String s : split) {
              -389            total.append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).append(' ');
              -390        }
              -391
              -392        return total.toString().trim();
              -393    }
              -394
              -395    public static String ltrim(String s) {
              -396        int i = 0;
              -397        while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
              -398            i++;
              -399        }
              -400        return s.substring(i);
              -401    }
              -402
              -403    public static String rtrim(String s) {
              -404        int i = s.length() - 1;
              -405        while (i >= 0 && Character.isWhitespace(s.charAt(i))) {
              -406            i--;
              -407        }
              -408        return s.substring(0, i + 1);
              -409    }
              -410
              -411    public static List<String> enumNames(Enum<?>[] values) {
              -412        return Stream.of(values).map(Enum::name).collect(Collectors.toList());
              -413    }
              -414
              -415    public static List<String> enumNames(Class<? extends Enum<?>> cls) {
              -416        return enumNames(cls.getEnumConstants());
              -417    }
              -418
              -419    public static String combine(String[] args) {
              -420        return combine(args, 0);
              -421    }
              -422
              -423    public static String combine(String[] args, int start) {
              -424        int size = 0;
              -425        for (int i = start; i < args.length; i++) {
              -426            size += args[i].length();
              -427        }
              -428        StringBuilder sb = new StringBuilder(size);
              -429        for (int i = start; i < args.length; i++) {
              -430            sb.append(args[i]);
              -431        }
              -432        return sb.toString();
              -433    }
              -434
              -435
              -436    @Nullable
              -437    public static <E extends Enum<E>> E simpleMatch(Class<? extends Enum<?>> list, String item) {
              -438        if (item == null) {
              -439            return null;
              -440        }
              -441        item = ACFUtil.simplifyString(item);
              -442        for (Enum<?> s : list.getEnumConstants()) {
              -443            String simple = ACFUtil.simplifyString(s.name());
              -444            if (item.equals(simple)) {
              -445                //noinspection unchecked
              -446                return (E) s;
              -447            }
              -448        }
              -449
              -450        return null;
              -451    }
              -452
              -453    public static boolean isTruthy(String test) {
              -454        switch (test) {
              -455            case "t":
              -456            case "true":
              -457            case "on":
              -458            case "y":
              -459            case "yes":
              -460            case "1":
              -461                return true;
              -462        }
              -463        return false;
              -464    }
              -465
              -466
              -467    public static Number parseNumber(String num, boolean suffixes) {
              -468        ApplyModifierToNumber applyModifierToNumber = new ApplyModifierToNumber(num, suffixes).invoke();
              -469        num = applyModifierToNumber.getNum();
              -470        double mod = applyModifierToNumber.getMod();
              -471
              -472        return Double.parseDouble(num) * mod;
              -473    }
              -474
              -475    public static BigDecimal parseBigNumber(String num, boolean suffixes) {
              -476        ApplyModifierToNumber applyModifierToNumber = new ApplyModifierToNumber(num, suffixes).invoke();
              -477        num = applyModifierToNumber.getNum();
              -478        double mod = applyModifierToNumber.getMod();
              -479
              -480        BigDecimal big = new BigDecimal(num);
              -481        return (mod == 1) ? big : big.multiply(new BigDecimal(mod));
              -482    }
              -483
              -484    public static <T> boolean hasIntersection(Collection<T> list1, Collection<T> list2) {
              -485        for (T t : list1) {
              -486            if (list2.contains(t)) {
              -487                return true;
              -488            }
              -489        }
              -490
              -491        return false;
              -492    }
              -493
              -494    public static <T> Collection<T> intersection(Collection<T> list1, Collection<T> list2) {
              -495        List<T> list = new ArrayList<>();
              -496
              -497        for (T t : list1) {
              -498            if (list2.contains(t)) {
              -499                list.add(t);
              -500            }
              -501        }
              -502
              -503        return list;
              -504    }
              -505
              -506    public static int rand(int min, int max) {
              -507        return min + RANDOM.nextInt(max - min + 1);
              -508    }
              -509
              -510    /**
              -511     * Calculate random between 2 points, excluding a center
              -512     * ex: Util.rand(-12, -6, 6, 12) would not return -5 to 5
              -513     *
              -514     * @param min1
              -515     * @param max1
              -516     * @param min2
              -517     * @param max2
              -518     * @return
              -519     */
              -520    public static int rand(int min1, int max1, int min2, int max2) {
              -521        return randBool() ? rand(min1, max1) : rand(min2, max2);
              -522    }
              -523
              -524    public static double rand(double min, double max) {
              -525        return RANDOM.nextDouble() * (max - min) + min;
              -526    }
              -527
              -528    public static boolean isNumber(String str) {
              -529        return ApacheCommonsLangUtil.isNumeric(str);
              -530    }
              -531
              -532    public static String intToRoman(int integer) {
              -533        if (integer == 1) {
              -534            return "I";
              -535        }
              -536        if (integer == 2) {
              -537            return "II";
              -538        }
              -539        if (integer == 3) {
              -540            return "III";
              -541        }
              -542        if (integer == 4) {
              -543            return "IV";
              -544        }
              -545        if (integer == 5) {
              -546            return "V";
              -547        }
              -548        if (integer == 6) {
              -549            return "VI";
              -550        }
              -551        if (integer == 7) {
              -552            return "VII";
              -553        }
              -554        if (integer == 8) {
              -555            return "VIII";
              -556        }
              -557        if (integer == 9) {
              -558            return "IX";
              -559        }
              -560        if (integer == 10) {
              -561            return "X";
              -562        }
              -563        return null;
              -564    }
              -565
              -566    public static boolean isInteger(String string) {
              -567        return ACFPatterns.INTEGER.matcher(string).matches();
              -568    }
              -569
              -570    public static boolean isFloat(String string) {
              -571        try {
              -572            //noinspection ResultOfMethodCallIgnored
              -573            Float.parseFloat(string);
              -574            return true;
              -575        } catch (Exception e) {
              -576            return false;
              -577        }
              -578    }
              -579
              -580    public static boolean isDouble(String string) {
              -581        try {
              -582            //noinspection ResultOfMethodCallIgnored
              -583            Double.parseDouble(string);
              -584            return true;
              -585        } catch (Exception e) {
              -586            return false;
              -587        }
              -588    }
              -589
              -590    public static boolean isBetween(float num, double min, double max) {
              -591        return num >= min && num <= max;
              -592    }
              -593
              -594    @SuppressWarnings("SameParameterValue")
              -595    public static double precision(double x, int p) {
              -596        double pow = Math.pow(10, p);
              -597        return Math.round(x * pow) / pow;
              -598    }
              -599
              -600    public static void sneaky(Throwable t) {
              -601        //noinspection RedundantTypeArguments
              -602        throw ACFUtil.<RuntimeException>superSneaky(t);
              -603    }
              -604
              -605    private static <T extends Throwable> T superSneaky(Throwable t) throws T {
              -606        //noinspection ConstantConditions,unchecked
              -607        throw (T) t;
              -608    }
              -609
              -610    public static <T> List<T> preformOnImmutable(List<T> list, Consumer<List<T>> action) {
              -611        try {
              -612            action.accept(list);
              -613        } catch (UnsupportedOperationException ex) {
              -614            list = new ArrayList<>(list);
              -615            action.accept(list);
              -616        }
              -617
              -618        return list;
              -619    }
              -620
              -621    public static <T> T getFirstElement(Iterable<T> iterable) {
              -622        if (iterable == null) {
              -623            return null;
              -624        }
              -625        Iterator<T> iterator = iterable.iterator();
              -626        if (iterator.hasNext()) {
              -627            return iterator.next();
              -628        }
              -629
              -630        return null;
              -631    }
              -632
              -633    private static class ApplyModifierToNumber {
              -634        private String num;
              -635        private boolean suffixes;
              -636        private double mod;
              -637
              -638        public ApplyModifierToNumber(String num, boolean suffixes) {
              -639            this.num = num;
              -640            this.suffixes = suffixes;
              -641        }
              -642
              -643        public String getNum() {
              -644            return num;
              -645        }
              -646
              -647        public double getMod() {
              -648            return mod;
              -649        }
              -650
              -651        public ApplyModifierToNumber invoke() {
              -652            mod = 1;
              -653            if (suffixes) {
              -654                switch (num.charAt(num.length() - 1)) {
              -655                    case 'M':
              -656                    case 'm':
              -657                        mod = 1000000D;
              -658                        num = num.substring(0, num.length() - 1);
              -659                        break;
              -660                    case 'K':
              -661                    case 'k':
              -662                        mod = 1000D;
              -663                        num = num.substring(0, num.length() - 1);
              -664                }
              -665            }
              -666            return this;
              -667        }
              -668    }
              -669}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026
              +027import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              +028import org.jetbrains.annotations.Nullable;
              +029
              +030import java.math.BigDecimal;
              +031import java.text.Normalizer;
              +032import java.text.Normalizer.Form;
              +033import java.text.NumberFormat;
              +034import java.util.ArrayList;
              +035import java.util.Collection;
              +036import java.util.Iterator;
              +037import java.util.List;
              +038import java.util.Locale;
              +039import java.util.Random;
              +040import java.util.function.Consumer;
              +041import java.util.regex.Matcher;
              +042import java.util.regex.Pattern;
              +043import java.util.stream.Collectors;
              +044import java.util.stream.Stream;
              +045
              +046@SuppressWarnings({"WeakerAccess", "unused"})
              +047public final class ACFUtil {
              +048
              +049    public static final Random RANDOM = new Random();
              +050
              +051    private ACFUtil() {
              +052    }
              +053
              +054    public static String padRight(String s, int n) {
              +055        return String.format("%1$-" + n + "s", s);
              +056    }
              +057
              +058    public static String padLeft(String s, int n) {
              +059        return String.format("%1$" + n + "s", s);
              +060    }
              +061
              +062    public static String formatNumber(Integer balance) {
              +063        return NumberFormat.getInstance().format(balance);
              +064    }
              +065
              +066    public static <T extends Enum> T getEnumFromName(T[] types, String name) {
              +067        return getEnumFromName(types, name, null);
              +068    }
              +069
              +070    public static <T extends Enum> T getEnumFromName(T[] types, String name, T def) {
              +071        for (T type : types) {
              +072            if (type.name().equalsIgnoreCase(name)) {
              +073                return type;
              +074            }
              +075        }
              +076        return def;
              +077    }
              +078
              +079    public static <T extends Enum> T getEnumFromOrdinal(T[] types, int ordinal) {
              +080        for (T type : types) {
              +081            if (type.ordinal() == ordinal) {
              +082                return type;
              +083            }
              +084        }
              +085        return null;
              +086    }
              +087
              +088    public static String ucfirst(String str) {
              +089        return ApacheCommonsLangUtil.capitalizeFully(str);
              +090    }
              +091
              +092    public static Double parseDouble(String var) {
              +093        return parseDouble(var, null);
              +094    }
              +095
              +096    public static Double parseDouble(String var, Double def) {
              +097        if (var == null) {
              +098            return def;
              +099        }
              +100        try {
              +101            return Double.parseDouble(var);
              +102        } catch (NumberFormatException ignored) {
              +103        }
              +104        return def;
              +105    }
              +106
              +107    public static Float parseFloat(String var) {
              +108        return parseFloat(var, null);
              +109    }
              +110
              +111    public static Float parseFloat(String var, Float def) {
              +112        if (var == null) {
              +113            return def;
              +114        }
              +115        try {
              +116            return Float.parseFloat(var);
              +117        } catch (NumberFormatException ignored) {
              +118        }
              +119        return def;
              +120    }
              +121
              +122    public static Long parseLong(String var) {
              +123        return parseLong(var, null);
              +124    }
              +125
              +126    public static Long parseLong(String var, Long def) {
              +127        if (var == null) {
              +128            return def;
              +129        }
              +130        try {
              +131            return Long.parseLong(var);
              +132        } catch (NumberFormatException ignored) {
              +133        }
              +134        return def;
              +135    }
              +136
              +137    public static Integer parseInt(String var) {
              +138        return parseInt(var, null);
              +139    }
              +140
              +141    public static Integer parseInt(String var, Integer def) {
              +142        if (var == null) {
              +143            return def;
              +144        }
              +145        try {
              +146            return Integer.parseInt(var);
              +147        } catch (NumberFormatException ignored) {
              +148        }
              +149        return def;
              +150    }
              +151
              +152    public static boolean randBool() {
              +153        return RANDOM.nextBoolean();
              +154    }
              +155
              +156    public static <T> T nullDefault(Object val, Object def) {
              +157        //noinspection unchecked
              +158        return (T) (val != null ? val : def);
              +159    }
              +160
              +161    public static String join(Collection<String> args) {
              +162        return ApacheCommonsLangUtil.join(args, " ");
              +163    }
              +164
              +165    public static String join(Collection<String> args, String sep) {
              +166        return ApacheCommonsLangUtil.join(args, sep);
              +167    }
              +168
              +169    public static String join(String[] args) {
              +170        return join(args, 0, ' ');
              +171    }
              +172
              +173    public static String join(String[] args, String sep) {
              +174        return ApacheCommonsLangUtil.join(args, sep);
              +175    }
              +176
              +177    public static String join(String[] args, char sep) {
              +178        return join(args, 0, sep);
              +179    }
              +180
              +181    public static String join(String[] args, int index) {
              +182        return join(args, index, ' ');
              +183    }
              +184
              +185    public static String join(String[] args, int index, char sep) {
              +186        return ApacheCommonsLangUtil.join(args, sep, index, args.length);
              +187    }
              +188
              +189    public static String simplifyString(String str) {
              +190        if (str == null) {
              +191            return null;
              +192        }
              +193        return ACFPatterns.NON_ALPHA_NUMERIC.matcher(str.toLowerCase(Locale.ENGLISH)).replaceAll("");
              +194    }
              +195
              +196    public static double round(double x, int scale) {
              +197        try {
              +198            return (new BigDecimal
              +199                    (Double.toString(x))
              +200                    .setScale(scale, BigDecimal.ROUND_HALF_UP))
              +201                    .doubleValue();
              +202        } catch (NumberFormatException ex) {
              +203            if (Double.isInfinite(x)) {
              +204                return x;
              +205            } else {
              +206                return Double.NaN;
              +207            }
              +208        }
              +209    }
              +210
              +211    public static int roundUp(int num, int multiple) {
              +212        if (multiple == 0) {
              +213            return num;
              +214        }
              +215
              +216        int remainder = num % multiple;
              +217        if (remainder == 0) {
              +218            return num;
              +219        }
              +220        return num + multiple - remainder;
              +221
              +222    }
              +223
              +224    public static String limit(String str, int limit) {
              +225        return str.length() > limit ? str.substring(0, limit) : str;
              +226    }
              +227
              +228    /**
              +229     * Plain string replacement, escapes replace value.
              +230     *
              +231     * @param string
              +232     * @param pattern
              +233     * @param repl
              +234     * @return
              +235     */
              +236    public static String replace(String string, Pattern pattern, String repl) {
              +237        return pattern.matcher(string).replaceAll(Matcher.quoteReplacement(repl));
              +238    }
              +239
              +240    /**
              +241     * Regex version of {@link #replace(String, Pattern, String)}
              +242     *
              +243     * @param string
              +244     * @param pattern
              +245     * @param repl
              +246     * @return
              +247     */
              +248    public static String replacePattern(String string, Pattern pattern, String repl) {
              +249        return pattern.matcher(string).replaceAll(repl);
              +250    }
              +251
              +252    /**
              +253     * Plain String replacement. If you need regex patterns, see {@link #replacePattern(String, String, String)}
              +254     *
              +255     * @param string
              +256     * @param pattern
              +257     * @param repl
              +258     * @return
              +259     */
              +260    public static String replace(String string, String pattern, String repl) {
              +261        return replace(string, ACFPatterns.getPattern(Pattern.quote(pattern)), repl);
              +262    }
              +263
              +264    /**
              +265     * Regex version of {@link #replace(String, String, String)}
              +266     *
              +267     * @param string
              +268     * @param pattern
              +269     * @param repl
              +270     * @return
              +271     */
              +272    public static String replacePattern(String string, String pattern, String repl) {
              +273        return replace(string, ACFPatterns.getPattern(pattern), repl);
              +274    }
              +275
              +276    /**
              +277     * Pure Regex Pattern matching and replacement, no escaping
              +278     *
              +279     * @param string
              +280     * @param pattern
              +281     * @param repl
              +282     * @return
              +283     */
              +284    public static String replacePatternMatch(String string, Pattern pattern, String repl) {
              +285        return pattern.matcher(string).replaceAll(repl);
              +286    }
              +287
              +288    /**
              +289     * Pure Regex Pattern matching and replacement, no escaping
              +290     *
              +291     * @param string
              +292     * @param pattern
              +293     * @param repl
              +294     * @return
              +295     */
              +296    public static String replacePatternMatch(String string, String pattern, String repl) {
              +297        return replacePatternMatch(string, ACFPatterns.getPattern(pattern), repl);
              +298    }
              +299
              +300    public static String replaceStrings(String string, String... replacements) {
              +301        if (replacements.length < 2 || replacements.length % 2 != 0) {
              +302            throw new IllegalArgumentException("Invalid Replacements");
              +303        }
              +304        for (int i = 0; i < replacements.length; i += 2) {
              +305            String key = replacements[i];
              +306            String value = replacements[i + 1];
              +307            if (value == null) value = "";
              +308            string = replace(string, key, value);
              +309        }
              +310        return string;
              +311    }
              +312
              +313    public static String replacePatterns(String string, String... replacements) {
              +314        if (replacements.length < 2 || replacements.length % 2 != 0) {
              +315            throw new IllegalArgumentException("Invalid Replacements");
              +316        }
              +317        for (int i = 0; i < replacements.length; i += 2) {
              +318            String key = replacements[i];
              +319            String value = replacements[i + 1];
              +320            if (value == null) value = "";
              +321            string = replacePattern(string, key, value);
              +322        }
              +323        return string;
              +324    }
              +325
              +326    public static String capitalize(String str, char[] delimiters) {
              +327        return ApacheCommonsLangUtil.capitalize(str, delimiters);
              +328    }
              +329
              +330    private static boolean isDelimiter(char ch, char[] delimiters) {
              +331        return ApacheCommonsLangUtil.isDelimiter(ch, delimiters);
              +332    }
              +333
              +334    public static <T> T random(List<T> arr) {
              +335        if (arr == null || arr.isEmpty()) {
              +336            return null;
              +337        }
              +338        return arr.get(RANDOM.nextInt(arr.size()));
              +339    }
              +340
              +341    public static <T> T random(T[] arr) {
              +342        if (arr == null || arr.length == 0) {
              +343            return null;
              +344        }
              +345        return arr[RANDOM.nextInt(arr.length)];
              +346    }
              +347
              +348    /**
              +349     * Added as im sure we will try to "Find this" again. This is no different than Enum.values() passed to above method logically
              +350     * but the array version is slightly faster.
              +351     *
              +352     * @param enm
              +353     * @param <T>
              +354     * @return
              +355     */
              +356    @Deprecated
              +357    public static <T extends Enum<?>> T random(Class<? extends T> enm) {
              +358        return random(enm.getEnumConstants());
              +359    }
              +360
              +361    public static String normalize(String s) {
              +362        if (s == null) {
              +363            return null;
              +364        }
              +365        return ACFPatterns.NON_PRINTABLE_CHARACTERS.matcher(Normalizer.normalize(s, Form.NFD)).replaceAll("");
              +366    }
              +367
              +368    public static int indexOf(String arg, String[] split) {
              +369        for (int i = 0; i < split.length; i++) {
              +370            if (arg == null) {
              +371                if (split[i] == null) {
              +372                    return i;
              +373                }
              +374            } else if (arg.equals(split[i])) {
              +375                return i;
              +376            }
              +377        }
              +378        return -1;
              +379    }
              +380
              +381    public static String capitalizeFirst(String name) {
              +382        return capitalizeFirst(name, '_');
              +383    }
              +384
              +385    public static String capitalizeFirst(String name, char separator) {
              +386        name = name.toLowerCase(Locale.ENGLISH);
              +387        String[] split = name.split(Character.toString(separator));
              +388        StringBuilder total = new StringBuilder(3);
              +389        for (String s : split) {
              +390            total.append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).append(' ');
              +391        }
              +392
              +393        return total.toString().trim();
              +394    }
              +395
              +396    public static String ltrim(String s) {
              +397        int i = 0;
              +398        while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
              +399            i++;
              +400        }
              +401        return s.substring(i);
              +402    }
              +403
              +404    public static String rtrim(String s) {
              +405        int i = s.length() - 1;
              +406        while (i >= 0 && Character.isWhitespace(s.charAt(i))) {
              +407            i--;
              +408        }
              +409        return s.substring(0, i + 1);
              +410    }
              +411
              +412    public static List<String> enumNames(Enum<?>[] values) {
              +413        return Stream.of(values).map(Enum::name).collect(Collectors.toList());
              +414    }
              +415
              +416    public static List<String> enumNames(Class<? extends Enum<?>> cls) {
              +417        return enumNames(cls.getEnumConstants());
              +418    }
              +419
              +420    public static String combine(String[] args) {
              +421        return combine(args, 0);
              +422    }
              +423
              +424    public static String combine(String[] args, int start) {
              +425        int size = 0;
              +426        for (int i = start; i < args.length; i++) {
              +427            size += args[i].length();
              +428        }
              +429        StringBuilder sb = new StringBuilder(size);
              +430        for (int i = start; i < args.length; i++) {
              +431            sb.append(args[i]);
              +432        }
              +433        return sb.toString();
              +434    }
              +435
              +436
              +437    @Nullable
              +438    public static <E extends Enum<E>> E simpleMatch(Class<? extends Enum<?>> list, String item) {
              +439        if (item == null) {
              +440            return null;
              +441        }
              +442        item = ACFUtil.simplifyString(item);
              +443        for (Enum<?> s : list.getEnumConstants()) {
              +444            String simple = ACFUtil.simplifyString(s.name());
              +445            if (item.equals(simple)) {
              +446                //noinspection unchecked
              +447                return (E) s;
              +448            }
              +449        }
              +450
              +451        return null;
              +452    }
              +453
              +454    public static boolean isTruthy(String test) {
              +455        switch (test) {
              +456            case "t":
              +457            case "true":
              +458            case "on":
              +459            case "y":
              +460            case "yes":
              +461            case "1":
              +462                return true;
              +463        }
              +464        return false;
              +465    }
              +466
              +467
              +468    public static Number parseNumber(String num, boolean suffixes) {
              +469        ApplyModifierToNumber applyModifierToNumber = new ApplyModifierToNumber(num, suffixes).invoke();
              +470        num = applyModifierToNumber.getNum();
              +471        double mod = applyModifierToNumber.getMod();
              +472
              +473        return Double.parseDouble(num) * mod;
              +474    }
              +475
              +476    public static BigDecimal parseBigNumber(String num, boolean suffixes) {
              +477        ApplyModifierToNumber applyModifierToNumber = new ApplyModifierToNumber(num, suffixes).invoke();
              +478        num = applyModifierToNumber.getNum();
              +479        double mod = applyModifierToNumber.getMod();
              +480
              +481        BigDecimal big = new BigDecimal(num);
              +482        return (mod == 1) ? big : big.multiply(new BigDecimal(mod));
              +483    }
              +484
              +485    public static <T> boolean hasIntersection(Collection<T> list1, Collection<T> list2) {
              +486        for (T t : list1) {
              +487            if (list2.contains(t)) {
              +488                return true;
              +489            }
              +490        }
              +491
              +492        return false;
              +493    }
              +494
              +495    public static <T> Collection<T> intersection(Collection<T> list1, Collection<T> list2) {
              +496        List<T> list = new ArrayList<>();
              +497
              +498        for (T t : list1) {
              +499            if (list2.contains(t)) {
              +500                list.add(t);
              +501            }
              +502        }
              +503
              +504        return list;
              +505    }
              +506
              +507    public static int rand(int min, int max) {
              +508        return min + RANDOM.nextInt(max - min + 1);
              +509    }
              +510
              +511    /**
              +512     * Calculate random between 2 points, excluding a center
              +513     * ex: Util.rand(-12, -6, 6, 12) would not return -5 to 5
              +514     *
              +515     * @param min1
              +516     * @param max1
              +517     * @param min2
              +518     * @param max2
              +519     * @return
              +520     */
              +521    public static int rand(int min1, int max1, int min2, int max2) {
              +522        return randBool() ? rand(min1, max1) : rand(min2, max2);
              +523    }
              +524
              +525    public static double rand(double min, double max) {
              +526        return RANDOM.nextDouble() * (max - min) + min;
              +527    }
              +528
              +529    public static boolean isNumber(String str) {
              +530        return ApacheCommonsLangUtil.isNumeric(str);
              +531    }
              +532
              +533    public static String intToRoman(int integer) {
              +534        if (integer == 1) {
              +535            return "I";
              +536        }
              +537        if (integer == 2) {
              +538            return "II";
              +539        }
              +540        if (integer == 3) {
              +541            return "III";
              +542        }
              +543        if (integer == 4) {
              +544            return "IV";
              +545        }
              +546        if (integer == 5) {
              +547            return "V";
              +548        }
              +549        if (integer == 6) {
              +550            return "VI";
              +551        }
              +552        if (integer == 7) {
              +553            return "VII";
              +554        }
              +555        if (integer == 8) {
              +556            return "VIII";
              +557        }
              +558        if (integer == 9) {
              +559            return "IX";
              +560        }
              +561        if (integer == 10) {
              +562            return "X";
              +563        }
              +564        return null;
              +565    }
              +566
              +567    public static boolean isInteger(String string) {
              +568        return ACFPatterns.INTEGER.matcher(string).matches();
              +569    }
              +570
              +571    public static boolean isFloat(String string) {
              +572        try {
              +573            //noinspection ResultOfMethodCallIgnored
              +574            Float.parseFloat(string);
              +575            return true;
              +576        } catch (Exception e) {
              +577            return false;
              +578        }
              +579    }
              +580
              +581    public static boolean isDouble(String string) {
              +582        try {
              +583            //noinspection ResultOfMethodCallIgnored
              +584            Double.parseDouble(string);
              +585            return true;
              +586        } catch (Exception e) {
              +587            return false;
              +588        }
              +589    }
              +590
              +591    public static boolean isBetween(float num, double min, double max) {
              +592        return num >= min && num <= max;
              +593    }
              +594
              +595    @SuppressWarnings("SameParameterValue")
              +596    public static double precision(double x, int p) {
              +597        double pow = Math.pow(10, p);
              +598        return Math.round(x * pow) / pow;
              +599    }
              +600
              +601    public static void sneaky(Throwable t) {
              +602        //noinspection RedundantTypeArguments
              +603        throw ACFUtil.<RuntimeException>superSneaky(t);
              +604    }
              +605
              +606    private static <T extends Throwable> T superSneaky(Throwable t) throws T {
              +607        //noinspection ConstantConditions,unchecked
              +608        throw (T) t;
              +609    }
              +610
              +611    public static <T> List<T> preformOnImmutable(List<T> list, Consumer<List<T>> action) {
              +612        try {
              +613            action.accept(list);
              +614        } catch (UnsupportedOperationException ex) {
              +615            list = new ArrayList<>(list);
              +616            action.accept(list);
              +617        }
              +618
              +619        return list;
              +620    }
              +621
              +622    public static <T> T getFirstElement(Iterable<T> iterable) {
              +623        if (iterable == null) {
              +624            return null;
              +625        }
              +626        Iterator<T> iterator = iterable.iterator();
              +627        if (iterator.hasNext()) {
              +628            return iterator.next();
              +629        }
              +630
              +631        return null;
              +632    }
              +633
              +634    private static class ApplyModifierToNumber {
              +635        private String num;
              +636        private boolean suffixes;
              +637        private double mod;
              +638
              +639        public ApplyModifierToNumber(String num, boolean suffixes) {
              +640            this.num = num;
              +641            this.suffixes = suffixes;
              +642        }
              +643
              +644        public String getNum() {
              +645            return num;
              +646        }
              +647
              +648        public double getMod() {
              +649            return mod;
              +650        }
              +651
              +652        public ApplyModifierToNumber invoke() {
              +653            mod = 1;
              +654            if (suffixes) {
              +655                switch (num.charAt(num.length() - 1)) {
              +656                    case 'M':
              +657                    case 'm':
              +658                        mod = 1000000D;
              +659                        num = num.substring(0, num.length() - 1);
              +660                        break;
              +661                    case 'K':
              +662                    case 'k':
              +663                        mod = 1000D;
              +664                        num = num.substring(0, num.length() - 1);
              +665                }
              +666            }
              +667            return this;
              +668        }
              +669    }
              +670}
               
               
               
              @@ -737,5 +739,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/AnnotationProcessor.html b/docs/acf-core/src-html/co/aikar/commands/AnnotationProcessor.html index 07e8b025..c64c7764 100644 --- a/docs/acf-core/src-html/co/aikar/commands/AnnotationProcessor.html +++ b/docs/acf-core/src-html/co/aikar/commands/AnnotationProcessor.html @@ -1,73 +1,74 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import org.jetbrains.annotations.Nullable;
              -027
              -028import java.lang.annotation.Annotation;
              -029import java.lang.reflect.Parameter;
              -030import java.util.Set;
              -031
              -032@Deprecated /* @deprecated UNFINISHED */
              -033public interface AnnotationProcessor <T extends Annotation> {
              -034
              -035    @Nullable
              -036    default Set<Class<?>> getApplicableParameters() {
              -037        return null;
              -038    }
              -039
              -040    default void onBaseCommandRegister(BaseCommand command, T annotation) {
              -041
              -042    }
              -043    default void onCommandRegistered(RegisteredCommand command, T annotation) {
              -044
              -045    }
              -046    default void onParameterRegistered(RegisteredCommand command, int parameterIndex, Parameter p, T annotation) {
              -047
              -048    }
              -049    default void onPreComand(CommandOperationContext context) {
              -050
              -051    }
              -052    default void onPostComand(CommandOperationContext context) {
              -053
              -054    }
              -055    default void onPreContextResolution(CommandExecutionContext context) {
              -056
              -057    }
              -058    default void onPostContextResolution(CommandExecutionContext context, Object resolvedValue) {
              -059
              -060    }
              -061
              -062}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import org.jetbrains.annotations.Nullable;
              +027
              +028import java.lang.annotation.Annotation;
              +029import java.lang.reflect.Parameter;
              +030import java.util.Set;
              +031
              +032@Deprecated /* @deprecated UNFINISHED */
              +033public interface AnnotationProcessor <T extends Annotation> {
              +034
              +035    @Nullable
              +036    default Set<Class<?>> getApplicableParameters() {
              +037        return null;
              +038    }
              +039
              +040    default void onBaseCommandRegister(BaseCommand command, T annotation) {
              +041
              +042    }
              +043    default void onCommandRegistered(RegisteredCommand command, T annotation) {
              +044
              +045    }
              +046    default void onParameterRegistered(RegisteredCommand command, int parameterIndex, Parameter p, T annotation) {
              +047
              +048    }
              +049    default void onPreComand(CommandOperationContext context) {
              +050
              +051    }
              +052    default void onPostComand(CommandOperationContext context) {
              +053
              +054    }
              +055    default void onPreContextResolution(CommandExecutionContext context) {
              +056
              +057    }
              +058    default void onPostContextResolution(CommandExecutionContext context, Object resolvedValue) {
              +059
              +060    }
              +061
              +062}
               
               
               
              @@ -130,5 +131,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/BaseCommand.html b/docs/acf-core/src-html/co/aikar/commands/BaseCommand.html index 479a30c1..5de6efbd 100644 --- a/docs/acf-core/src-html/co/aikar/commands/BaseCommand.html +++ b/docs/acf-core/src-html/co/aikar/commands/BaseCommand.html @@ -1,852 +1,854 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.CommandRouter.RouteSearch;
              -027import co.aikar.commands.annotation.CatchAll;
              -028import co.aikar.commands.annotation.CatchUnknown;
              -029import co.aikar.commands.annotation.CommandAlias;
              -030import co.aikar.commands.annotation.CommandPermission;
              -031import co.aikar.commands.annotation.Conditions;
              -032import co.aikar.commands.annotation.Default;
              -033import co.aikar.commands.annotation.Description;
              -034import co.aikar.commands.annotation.HelpCommand;
              -035import co.aikar.commands.annotation.PreCommand;
              -036import co.aikar.commands.annotation.Subcommand;
              -037import co.aikar.commands.annotation.UnknownHandler;
              -038import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              -039import com.google.common.collect.HashMultimap;
              -040import com.google.common.collect.SetMultimap;
              -041import org.jetbrains.annotations.Nullable;
              -042
              -043import java.lang.reflect.Constructor;
              -044import java.lang.reflect.InvocationTargetException;
              -045import java.lang.reflect.Method;
              -046import java.lang.reflect.Parameter;
              -047import java.util.ArrayList;
              -048import java.util.Arrays;
              -049import java.util.Collections;
              -050import java.util.HashMap;
              -051import java.util.HashSet;
              -052import java.util.LinkedHashSet;
              -053import java.util.List;
              -054import java.util.Map;
              -055import java.util.Objects;
              -056import java.util.Set;
              -057import java.util.Stack;
              -058import java.util.stream.Collectors;
              -059import java.util.stream.Stream;
              -060
              -061/**
              -062 * A Base command is defined as a command group of related commands.
              -063 * A BaseCommand does not imply nor enforce that they use the same root command.
              -064 * <p>
              -065 * It is up to the end user how to organize their command. you could use 1 base command per
              -066 * command in your application.
              -067 * <p>
              -068 * Optionally (and encouraged), you can use the base command to represent a root command, and
              -069 * then each actionable command is a sub command
              -070 */
              -071
              -072public abstract class BaseCommand {
              -073
              -074    /**
              -075     * This is a field which contains the magic key in the {@link #subCommands} map for the method to catch any unknown
              -076     * argument to command states.
              -077     */
              -078    static final String CATCHUNKNOWN = "__catchunknown";
              -079    /**
              -080     * This is a field which contains the magic key in the {@link #subCommands} map for the method which is default for the
              -081     * entire base command.
              -082     */
              -083    static final String DEFAULT = "__default";
              -084
              -085    /**
              -086     * A map of all the registered commands for this base command, keyed to each potential subcommand to access it.
              -087     */
              -088    final SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
              -089    final Set<BaseCommand> subScopes = new HashSet<>();
              -090
              -091    /**
              -092     * A map of flags to pass to Context Resolution for every parameter of the type. This is like an automatic @Flags on each.
              -093     */
              -094    final Map<Class<?>, String> contextFlags = new HashMap<>();
              -095
              -096    /**
              -097     * What method was annoated with {@link PreCommand} to execute before commands.
              -098     */
              -099    @Nullable
              -100    private Method preCommandHandler;
              -101
              -102    /**
              -103     * What root command the user actually entered to access the currently executing command
              -104     */
              -105    @SuppressWarnings("WeakerAccess")
              -106    private String execLabel;
              -107    /**
              -108     * What subcommand the user actually entered to access the currently executing command
              -109     */
              -110    @SuppressWarnings("WeakerAccess")
              -111    private String execSubcommand;
              -112    /**
              -113     * What arguments the user actually entered after the root command to access the currently executing command
              -114     */
              -115    @SuppressWarnings("WeakerAccess")
              -116    private String[] origArgs;
              -117
              -118    /**
              -119     * The manager this is registered to
              -120     */
              -121    CommandManager<?, ?, ?, ?, ?, ?> manager = null;
              -122
              -123    /**
              -124     * The command which owns this. This may be null if there are no owners.
              -125     */
              -126    BaseCommand parentCommand;
              -127    Map<String, RootCommand> registeredCommands = new HashMap<>();
              -128    /**
              -129     * The description of the command. This may be null if no description has been provided.
              -130     * Used for help documentation
              -131     */
              -132    @Nullable String description;
              -133    /**
              -134     * The name of the command. This may be null if no name has been provided.
              -135     */
              -136    @Nullable String commandName;
              -137    /**
              -138     * The permission of the command. This may be null if no permission has been provided.
              -139     */
              -140    @Nullable String permission;
              -141    /**
              -142     * The conditions of the command. This may be null if no conditions has been provided.
              -143     */
              -144    @Nullable String conditions;
              -145    /**
              -146     * Identifies if the command has an explicit help command annotated with {@link HelpCommand}
              -147     */
              -148    boolean hasHelpCommand;
              -149
              -150    /**
              -151     * The handler of all uncaught exceptions thrown by the user's command implementation.
              -152     */
              -153    private ExceptionHandler exceptionHandler = null;
              -154    /**
              -155     * The last operative context data of this command. This may be null if this command hasn't been run yet.
              -156     */
              -157    private final ThreadLocal<CommandOperationContext> lastCommandOperationContext = new ThreadLocal<>();
              -158    /**
              -159     * If a parent exists to this command, and it has  a Subcommand annotation, prefix all subcommands in this class with this
              -160     */
              -161    @Nullable
              -162    private String parentSubcommand;
              -163
              -164    /**
              -165     * The permissions of the command.
              -166     */
              -167    private final Set<String> permissions = new HashSet<>();
              -168
              -169    public BaseCommand() {
              -170    }
              -171
              -172    /**
              -173     * Constructor based defining of commands will be removed in the next version bump.
              -174     *
              -175     * @param cmd
              -176     * @deprecated Please switch to {@link CommandAlias} for defining all root commands.
              -177     */
              -178    @Deprecated
              -179    public BaseCommand(@Nullable String cmd) {
              -180        this.commandName = cmd;
              -181    }
              -182
              -183    /**
              -184     * Returns a reference to the last used CommandOperationContext.
              -185     * This method is ThreadLocal, in that it can only be used on a thread that has executed a command
              -186     *
              -187     * @return
              -188     */
              -189    public CommandOperationContext getLastCommandOperationContext() {
              -190        return lastCommandOperationContext.get();
              -191    }
              -192
              -193    /**
              -194     * Gets the root command name that the user actually typed
              -195     *
              -196     * @return Name
              -197     */
              -198    public String getExecCommandLabel() {
              -199        return execLabel;
              -200    }
              -201
              -202    /**
              -203     * Gets the actual sub command name the user typed
              -204     *
              -205     * @return Name
              -206     */
              -207    public String getExecSubcommand() {
              -208        return execSubcommand;
              -209    }
              -210
              -211    /**
              -212     * Gets the actual args in string form the user typed
              -213     *
              -214     * @return Args
              -215     */
              -216    public String[] getOrigArgs() {
              -217        return origArgs;
              -218    }
              -219
              -220    /**
              -221     * This should be called whenever the command gets registered.
              -222     * It sets all required fields correctly and injects dependencies.
              -223     *
              -224     * @param manager The manager to register as this command's owner and handler.
              -225     */
              -226    void onRegister(CommandManager manager) {
              -227        onRegister(manager, this.commandName);
              -228    }
              -229
              -230    /**
              -231     * This should be called whenever the command gets registered.
              -232     * It sets all required fields correctly and injects dependencies.
              -233     *
              -234     * @param manager The manager to register as this command's owner and handler.
              -235     * @param cmd     The command name to use register with.
              -236     */
              -237    private void onRegister(CommandManager manager, String cmd) {
              -238        manager.injectDependencies(this);
              -239        this.manager = manager;
              -240
              -241        final Annotations annotations = manager.getAnnotations();
              -242        final Class<? extends BaseCommand> self = this.getClass();
              -243
              -244        String[] cmdAliases = annotations.getAnnotationValues(self, CommandAlias.class, Annotations.REPLACEMENTS | Annotations.LOWERCASE | Annotations.NO_EMPTY);
              -245
              -246        if (cmd == null && cmdAliases != null) {
              -247            cmd = cmdAliases[0];
              -248        }
              -249
              -250        this.commandName = cmd != null ? cmd : self.getSimpleName().toLowerCase();
              -251        this.permission = annotations.getAnnotationValue(self, CommandPermission.class, Annotations.REPLACEMENTS);
              -252        this.description = annotations.getAnnotationValue(self, Description.class, Annotations.NO_EMPTY | Annotations.REPLACEMENTS);
              -253        this.parentSubcommand = getParentSubcommand(self);
              -254        this.conditions = annotations.getAnnotationValue(self, Conditions.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              -255
              -256        computePermissions(); // Must be before any subcommands so they can inherit permissions
              -257        registerSubcommands();
              -258        registerSubclasses(cmd);
              -259
              -260        if (cmdAliases != null) {
              -261            Set<String> cmdList = new HashSet<>();
              -262            Collections.addAll(cmdList, cmdAliases);
              -263            cmdList.remove(cmd);
              -264            for (String cmdAlias : cmdList) {
              -265                register(cmdAlias, this);
              -266            }
              -267        }
              -268
              -269        if (cmd != null) {
              -270            register(cmd, this);
              -271        }
              -272    }
              -273
              -274    /**
              -275     * This recursively registers all subclasses of the command as subcommands, if they are of type {@link BaseCommand}.
              -276     *
              -277     * @param cmd The command name of this command.
              -278     */
              -279    private void registerSubclasses(String cmd) {
              -280        for (Class<?> clazz : this.getClass().getDeclaredClasses()) {
              -281            if (BaseCommand.class.isAssignableFrom(clazz)) {
              -282                try {
              -283                    BaseCommand subScope = null;
              -284                    Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
              -285                    for (Constructor<?> declaredConstructor : declaredConstructors) {
              -286
              -287                        declaredConstructor.setAccessible(true);
              -288                        Parameter[] parameters = declaredConstructor.getParameters();
              -289                        if (parameters.length == 1) {
              -290                            subScope = (BaseCommand) declaredConstructor.newInstance(this);
              -291                        } else {
              -292                            manager.log(LogLevel.INFO, "Found unusable constructor: " + declaredConstructor.getName() + "(" + Stream.of(parameters).map(p -> p.getType().getSimpleName() + " " + p.getName()).collect(Collectors.joining("<c2>,</c2> ")) + ")");
              -293                        }
              -294                    }
              -295                    if (subScope != null) {
              -296                        subScope.parentCommand = this;
              -297                        this.subScopes.add(subScope);
              -298                        subScope.onRegister(manager, cmd);
              -299                        this.subCommands.putAll(subScope.subCommands);
              -300                        this.registeredCommands.putAll(subScope.registeredCommands);
              -301                    } else {
              -302                        this.manager.log(LogLevel.ERROR, "Could not find a subcommand ctor for " + clazz.getName());
              -303                    }
              -304                } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
              -305                    this.manager.log(LogLevel.ERROR, "Error registering subclass", e);
              -306                }
              -307            }
              -308        }
              -309    }
              -310
              -311    /**
              -312     * This registers all subcommands of the command.
              -313     */
              -314    private void registerSubcommands() {
              -315        final Annotations annotations = manager.getAnnotations();
              -316        boolean foundCatchUnknown = false;
              -317        boolean isParentEmpty = parentSubcommand == null || parentSubcommand.isEmpty();
              -318        Set<Method> methods = new LinkedHashSet<>();
              -319        Collections.addAll(methods, this.getClass().getDeclaredMethods());
              -320        Collections.addAll(methods, this.getClass().getMethods());
              -321
              -322        for (Method method : methods) {
              -323            method.setAccessible(true);
              -324            String sublist = null;
              -325            String sub = getSubcommandValue(method);
              -326            final String helpCommand = annotations.getAnnotationValue(method, HelpCommand.class, Annotations.NOTHING);
              -327            final String commandAliases = annotations.getAnnotationValue(method, CommandAlias.class, Annotations.NOTHING);
              -328
              -329            if (annotations.hasAnnotation(method, Default.class)) {
              -330                if (!isParentEmpty) {
              -331                    sub = parentSubcommand;
              -332                } else {
              -333                    registerSubcommand(method, DEFAULT);
              -334                }
              -335            }
              -336
              -337            if (sub != null) {
              -338                sublist = sub;
              -339            } else if (commandAliases != null) {
              -340                sublist = commandAliases;
              -341            } else if (helpCommand != null) {
              -342                sublist = helpCommand;
              -343                hasHelpCommand = true;
              -344            }
              -345
              -346            boolean preCommand = annotations.hasAnnotation(method, PreCommand.class);
              -347            boolean hasCatchUnknown = annotations.hasAnnotation(method, CatchUnknown.class) ||
              -348                    annotations.hasAnnotation(method, CatchAll.class) ||
              -349                    annotations.hasAnnotation(method, UnknownHandler.class);
              -350
              -351            if (hasCatchUnknown || (!foundCatchUnknown && helpCommand != null)) {
              -352                if (!foundCatchUnknown) {
              -353                    if (hasCatchUnknown) {
              -354                        this.subCommands.get(CATCHUNKNOWN).clear();
              -355                        foundCatchUnknown = true;
              -356                    }
              -357                    registerSubcommand(method, CATCHUNKNOWN);
              -358                } else {
              -359                    ACFUtil.sneaky(new IllegalStateException("Multiple @CatchUnknown/@HelpCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName()));
              -360                }
              -361            } else if (preCommand) {
              -362                if (this.preCommandHandler == null) {
              -363                    this.preCommandHandler = method;
              -364                } else {
              -365                    ACFUtil.sneaky(new IllegalStateException("Multiple @PreCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName()));
              -366                }
              -367            }
              -368            if (Objects.equals(method.getDeclaringClass(), this.getClass()) && sublist != null) {
              -369                registerSubcommand(method, sublist);
              -370            }
              -371        }
              -372    }
              -373
              -374    /**
              -375     * This registers all the permissions required to execute this command.
              -376     */
              -377    private void computePermissions() {
              -378        this.permissions.clear();
              -379        if (this.permission != null && !this.permission.isEmpty()) {
              -380            this.permissions.addAll(Arrays.asList(ACFPatterns.COMMA.split(this.permission)));
              -381        }
              -382        if (this.parentCommand != null) {
              -383            this.permissions.addAll(this.parentCommand.getRequiredPermissions());
              -384        }
              -385        this.subCommands.values().forEach(RegisteredCommand::computePermissions);
              -386        this.subScopes.forEach(BaseCommand::computePermissions);
              -387    }
              -388
              -389    /**
              -390     * Gets the subcommand name of the method given.
              -391     *
              -392     * @param method The method to check.
              -393     * @return The name of the subcommand. It returns null if the input doesn't have {@link Subcommand} attached.
              -394     */
              -395    private String getSubcommandValue(Method method) {
              -396        final String sub = manager.getAnnotations().getAnnotationValue(method, Subcommand.class, Annotations.NOTHING);
              -397        if (sub == null) {
              -398            return null;
              -399        }
              -400        Class<?> clazz = method.getDeclaringClass();
              -401        String parent = getParentSubcommand(clazz);
              -402        return parent == null || parent.isEmpty() ? sub : parent + " " + sub;
              -403    }
              -404
              -405    private String getParentSubcommand(Class<?> clazz) {
              -406        List<String> subList = new ArrayList<>();
              -407        while (clazz != null) {
              -408            String sub = manager.getAnnotations().getAnnotationValue(clazz, Subcommand.class, Annotations.NOTHING);
              -409            if (sub != null) {
              -410                subList.add(sub);
              -411            }
              -412            clazz = clazz.getEnclosingClass();
              -413        }
              -414        Collections.reverse(subList);
              -415        return ACFUtil.join(subList, " ");
              -416    }
              -417
              -418    /**
              -419     * Registers the given {@link BaseCommand cmd} as a child of the {@link RootCommand} linked to the name given.
              -420     *
              -421     * @param name Name of the parent to cmd.
              -422     * @param cmd  The {@link BaseCommand} to add as a child to the {@link RootCommand} owned name field.
              -423     */
              -424    private void register(String name, BaseCommand cmd) {
              -425        String nameLower = name.toLowerCase();
              -426        RootCommand rootCommand = manager.obtainRootCommand(nameLower);
              -427        rootCommand.addChild(cmd);
              -428
              -429        this.registeredCommands.put(nameLower, rootCommand);
              -430    }
              -431
              -432    /**
              -433     * Registers the given {@link Method} as a subcommand.
              -434     *
              -435     * @param method     The method to register as a subcommand.
              -436     * @param subCommand The subcommand's name(s).
              -437     */
              -438    private void registerSubcommand(Method method, String subCommand) {
              -439        subCommand = manager.getCommandReplacements().replace(subCommand.toLowerCase());
              -440        final String[] subCommandParts = ACFPatterns.SPACE.split(subCommand);
              -441        // Must run getSubcommandPossibility BEFORE we rewrite it just after this.
              -442        Set<String> cmdList = getSubCommandPossibilityList(subCommandParts);
              -443
              -444        // Strip pipes off for auto complete addition
              -445        for (int i = 0; i < subCommandParts.length; i++) {
              -446            String[] split = ACFPatterns.PIPE.split(subCommandParts[i]);
              -447            if (split.length == 0 || split[0].isEmpty()) {
              -448                throw new IllegalArgumentException("Invalid @Subcommand configuration for " + method.getName() + " - parts can not start with | or be empty");
              -449            }
              -450            subCommandParts[i] = split[0];
              -451        }
              -452        String prefSubCommand = ApacheCommonsLangUtil.join(subCommandParts, " ");
              -453        final String[] aliasNames = manager.getAnnotations().getAnnotationValues(method, CommandAlias.class, Annotations.REPLACEMENTS | Annotations.LOWERCASE);
              -454
              -455        String cmdName = aliasNames != null ? aliasNames[0] : this.commandName + " ";
              -456        RegisteredCommand cmd = manager.createRegisteredCommand(this, cmdName, method, prefSubCommand);
              -457
              -458        for (String subcmd : cmdList) {
              -459            subCommands.put(subcmd, cmd);
              -460        }
              -461        cmd.addSubcommands(cmdList);
              -462
              -463        if (aliasNames != null) {
              -464            for (String name : aliasNames) {
              -465                register(name, new ForwardingCommand(this, cmd, subCommandParts));
              -466            }
              -467        }
              -468    }
              -469
              -470    /**
              -471     * Takes a string like "foo|bar baz|qux" and generates a list of
              -472     * - foo baz
              -473     * - foo qux
              -474     * - bar baz
              -475     * - bar qux
              -476     * <p>
              -477     * For every possible sub command combination
              -478     *
              -479     * @param subCommandParts
              -480     * @return List of all sub command possibilities
              -481     */
              -482    private static Set<String> getSubCommandPossibilityList(String[] subCommandParts) {
              -483        int i = 0;
              -484        Set<String> current = null;
              -485        while (true) {
              -486            Set<String> newList = new HashSet<>();
              -487
              -488            if (i < subCommandParts.length) {
              -489                for (String s1 : ACFPatterns.PIPE.split(subCommandParts[i])) {
              -490                    if (current != null) {
              -491                        newList.addAll(current.stream().map(s -> s + " " + s1).collect(Collectors.toList()));
              -492                    } else {
              -493                        newList.add(s1);
              -494                    }
              -495                }
              -496            }
              -497
              -498            if (i + 1 < subCommandParts.length) {
              -499                current = newList;
              -500                i = i + 1;
              -501                continue;
              -502            }
              -503
              -504            return newList;
              -505        }
              -506    }
              -507
              -508    void execute(CommandIssuer issuer, CommandRouter.CommandRouteResult command) {
              -509        try {
              -510            CommandOperationContext commandContext = preCommandOperation(issuer, command.commandLabel, command.args, false);
              -511            execSubcommand = command.subcommand;
              -512            executeCommand(commandContext, issuer, command.args, command.cmd);
              -513        } finally {
              -514            postCommandOperation();
              -515        }
              -516    }
              -517
              -518    /**
              -519     * This is ran after any command operation has been performed.
              -520     */
              -521    private void postCommandOperation() {
              -522        CommandManager.commandOperationContext.get().pop();
              -523        execSubcommand = null;
              -524        execLabel = null;
              -525        origArgs = new String[]{};
              -526    }
              -527
              -528    /**
              -529     * This is ran before any command operation has been performed.
              -530     *
              -531     * @param issuer       The user who executed the command.
              -532     * @param commandLabel The label the user used to execute the command. This is not the command name, but their input.
              -533     *                     When there is multiple aliases, this is which alias was used
              -534     * @param args         The arguments passed to the command when executing it.
              -535     * @param isAsync      Whether the command is executed off of the main thread.
              -536     * @return The context which is being registered to the {@link CommandManager}'s {@link
              -537     * CommandManager#commandOperationContext thread local stack}.
              -538     */
              -539    private CommandOperationContext preCommandOperation(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) {
              -540        Stack<CommandOperationContext> contexts = CommandManager.commandOperationContext.get();
              -541        CommandOperationContext context = this.manager.createCommandOperationContext(this, issuer, commandLabel, args, isAsync);
              -542        contexts.push(context);
              -543        lastCommandOperationContext.set(context);
              -544        execSubcommand = null;
              -545        execLabel = commandLabel;
              -546        origArgs = args;
              -547        return context;
              -548    }
              -549
              -550    /**
              -551     * Gets the current command issuer.
              -552     *
              -553     * @return The current command issuer.
              -554     */
              -555    public CommandIssuer getCurrentCommandIssuer() {
              -556        return CommandManager.getCurrentCommandIssuer();
              -557    }
              -558
              -559    /**
              -560     * Gets the current command manager.
              -561     *
              -562     * @return The current command manager.
              -563     */
              -564    public CommandManager getCurrentCommandManager() {
              -565        return CommandManager.getCurrentCommandManager();
              -566    }
              -567
              -568    private void executeCommand(CommandOperationContext commandOperationContext,
              -569                                CommandIssuer issuer, String[] args, RegisteredCommand cmd) {
              -570        if (cmd.hasPermission(issuer)) {
              -571            commandOperationContext.setRegisteredCommand(cmd);
              -572            if (checkPrecommand(commandOperationContext, cmd, issuer, args)) {
              -573                return;
              -574            }
              -575            List<String> sargs = Arrays.asList(args);
              -576            cmd.invoke(issuer, sargs, commandOperationContext);
              -577        } else {
              -578            issuer.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED);
              -579        }
              -580    }
              -581
              -582    /**
              -583     * Please use command conditions for restricting execution
              -584     *
              -585     * @param issuer
              -586     * @param cmd
              -587     * @return
              -588     * @deprecated See {@link CommandConditions}
              -589     */
              -590    @SuppressWarnings("DeprecatedIsStillUsed")
              -591    @Deprecated
              -592    public boolean canExecute(CommandIssuer issuer, RegisteredCommand<?> cmd) {
              -593        return true;
              -594    }
              -595
              -596    /**
              -597     * Gets tab completed data from the given command from the user.
              -598     *
              -599     * @param issuer       The user who executed the tabcomplete.
              -600     * @param commandLabel The label which is being used by the user.
              -601     * @param args         The arguments the user has typed so far.
              -602     * @return All possibilities in the tab complete.
              -603     */
              -604    public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args) {
              -605        return tabComplete(issuer, commandLabel, args, false);
              -606    }
              -607
              -608    /**
              -609     * Gets the tab complete suggestions from a given command. This will automatically find anything
              -610     * which is valid for the specified command through the command's implementation.
              -611     *
              -612     * @param issuer       The issuer of the command.
              -613     * @param commandLabel The command name as entered by the user instead of the ACF registered name.
              -614     * @param args         All arguments entered by the user.
              -615     * @param isAsync      Whether this is run off of the main thread.
              -616     * @return The possibilities to tab complete in no particular order.
              -617     */
              -618    @SuppressWarnings("WeakerAccess")
              -619    public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync)
              -620            throws IllegalArgumentException {
              -621        return tabComplete(issuer, manager.getRootCommand(commandLabel.toLowerCase()), args, isAsync);
              -622    }
              -623
              -624    List<String> tabComplete(CommandIssuer issuer, RootCommand rootCommand, String[] args, boolean isAsync)
              -625            throws IllegalArgumentException {
              -626        if (args.length == 0) {
              -627            args = new String[]{""};
              -628        }
              -629        String commandLabel = rootCommand.getCommandName();
              -630        try {
              -631            CommandRouter router = manager.getRouter();
              -632
              -633            preCommandOperation(issuer, commandLabel, args, isAsync);
              -634
              -635            final RouteSearch search = router.routeCommand(rootCommand, commandLabel, args, true);
              -636
              -637            final List<String> cmds = new ArrayList<>();
              -638            if (search != null) {
              -639                CommandRouter.CommandRouteResult result = router.matchCommand(search, true);
              -640                if (result != null) {
              -641                    cmds.addAll(completeCommand(issuer, result.cmd, result.args, commandLabel, isAsync));
              -642                }
              -643            }
              -644
              -645            return filterTabComplete(args[args.length - 1], cmds);
              -646        } finally {
              -647            postCommandOperation();
              -648        }
              -649    }
              -650
              -651    /**
              -652     * Gets all subcommands which are possible to tabcomplete.
              -653     *
              -654     * @param issuer The command issuer.
              -655     * @param args
              -656     * @return
              -657     */
              -658    List<String> getCommandsForCompletion(CommandIssuer issuer, String[] args) {
              -659        final Set<String> cmds = new HashSet<>();
              -660        final int cmdIndex = Math.max(0, args.length - 1);
              -661        String argString = ApacheCommonsLangUtil.join(args, " ").toLowerCase();
              -662        for (Map.Entry<String, RegisteredCommand> entry : subCommands.entries()) {
              -663            final String key = entry.getKey();
              -664            if (key.startsWith(argString) && !CATCHUNKNOWN.equals(key) && !DEFAULT.equals(key)) {
              -665                final RegisteredCommand value = entry.getValue();
              -666                if (!value.hasPermission(issuer) || value.isPrivate) {
              -667                    continue;
              -668                }
              -669
              -670                String[] split = ACFPatterns.SPACE.split(value.prefSubCommand);
              -671                cmds.add(split[cmdIndex]);
              -672            }
              -673        }
              -674        return new ArrayList<>(cmds);
              -675    }
              -676
              -677    /**
              -678     * Complete a command properly per issuer and input.
              -679     *
              -680     * @param issuer       The user who executed this.
              -681     * @param cmd          The command to be completed.
              -682     * @param args         All arguments given by the user.
              -683     * @param commandLabel The command name the user used.
              -684     * @param isAsync      Whether the command was executed async.
              -685     * @return All results to complete the command.
              -686     */
              -687    private List<String> completeCommand(CommandIssuer issuer, RegisteredCommand cmd, String[] args, String commandLabel, boolean isAsync) {
              -688        if (!cmd.hasPermission(issuer) || args.length == 0 || cmd.parameters.length == 0) {
              -689            return Collections.emptyList();
              -690        }
              -691
              -692        if (!cmd.parameters[cmd.parameters.length - 1].consumesRest && args.length > cmd.consumeInputResolvers) {
              -693            return Collections.emptyList();
              -694        }
              -695
              -696        List<String> cmds = manager.getCommandCompletions().of(cmd, issuer, args, isAsync);
              -697        return filterTabComplete(args[args.length - 1], cmds);
              -698    }
              -699
              -700    /**
              -701     * Gets the actual args in string form the user typed
              -702     * This returns a list of all tab complete options which are possible with the given argument and commands.
              -703     *
              -704     * @param arg  Argument which was pressed tab on.
              -705     * @param cmds The possibilities to return.
              -706     * @return All possible options. This may be empty.
              -707     */
              -708    private static List<String> filterTabComplete(String arg, List<String> cmds) {
              -709        return cmds.stream()
              -710                .distinct()
              -711                .filter(cmd -> cmd != null && (arg.isEmpty() || ApacheCommonsLangUtil.startsWithIgnoreCase(cmd, arg)))
              -712                .collect(Collectors.toList());
              -713    }
              -714
              -715    /**
              -716     * Executes the precommand and sees whether something is wrong. Ideally, you get false from this.
              -717     *
              -718     * @param commandOperationContext The context to use.
              -719     * @param cmd                     The command executed.
              -720     * @param issuer                  The issuer who executed the command.
              -721     * @param args                    The arguments the issuer provided.
              -722     * @return Whether something went wrong.
              -723     */
              -724    private boolean checkPrecommand(CommandOperationContext commandOperationContext, RegisteredCommand cmd, CommandIssuer issuer, String[] args) {
              -725        Method pre = this.preCommandHandler;
              -726        if (pre != null) {
              -727            try {
              -728                Class<?>[] types = pre.getParameterTypes();
              -729                Object[] parameters = new Object[pre.getParameterCount()];
              -730                for (int i = 0; i < parameters.length; i++) {
              -731                    Class<?> type = types[i];
              -732                    Object issuerObject = issuer.getIssuer();
              -733                    if (manager.isCommandIssuer(type) && type.isAssignableFrom(issuerObject.getClass())) {
              -734                        parameters[i] = issuerObject;
              -735                    } else if (CommandIssuer.class.isAssignableFrom(type)) {
              -736                        parameters[i] = issuer;
              -737                    } else if (RegisteredCommand.class.isAssignableFrom(type)) {
              -738                        parameters[i] = cmd;
              -739                    } else if (String[].class.isAssignableFrom((type))) {
              -740                        parameters[i] = args;
              -741                    } else {
              -742                        parameters[i] = null;
              -743                    }
              -744                }
              -745
              -746                return (boolean) pre.invoke(this, parameters);
              -747            } catch (IllegalAccessException | InvocationTargetException e) {
              -748                this.manager.log(LogLevel.ERROR, "Exception encountered while command pre-processing", e);
              -749            }
              -750        }
              -751        return false;
              -752    }
              -753
              -754    /**
              -755     * @deprecated Unstable API
              -756     */
              -757    @Deprecated
              -758    @UnstableAPI
              -759    public CommandHelp getCommandHelp() {
              -760        return manager.generateCommandHelp();
              -761    }
              -762
              -763    /**
              -764     * @deprecated Unstable API
              -765     */
              -766    @Deprecated
              -767    @UnstableAPI
              -768    public void showCommandHelp() {
              -769        getCommandHelp().showHelp();
              -770    }
              -771
              -772    public void help(Object issuer, String[] args) {
              -773        help(manager.getCommandIssuer(issuer), args);
              -774    }
              -775
              -776    public void help(CommandIssuer issuer, String[] args) {
              -777        issuer.sendMessage(MessageType.ERROR, MessageKeys.UNKNOWN_COMMAND);
              -778    }
              -779
              -780    public void doHelp(Object issuer, String... args) {
              -781        doHelp(manager.getCommandIssuer(issuer), args);
              -782    }
              -783
              -784    public void doHelp(CommandIssuer issuer, String... args) {
              -785        help(issuer, args);
              -786    }
              -787
              -788    public void showSyntax(CommandIssuer issuer, RegisteredCommand<?> cmd) {
              -789        issuer.sendMessage(MessageType.SYNTAX, MessageKeys.INVALID_SYNTAX,
              -790                "{command}", manager.getCommandPrefix(issuer) + cmd.command,
              -791                "{syntax}", cmd.syntaxText
              -792        );
              -793    }
              -794
              -795    public boolean hasPermission(Object issuer) {
              -796        return hasPermission(manager.getCommandIssuer(issuer));
              -797    }
              -798
              -799    public boolean hasPermission(CommandIssuer issuer) {
              -800        return this.manager.hasPermission(issuer, getRequiredPermissions());
              -801    }
              -802
              -803    public Set<String> getRequiredPermissions() {
              -804        return this.permissions;
              -805    }
              -806
              -807    public boolean requiresPermission(String permission) {
              -808        return getRequiredPermissions().contains(permission);
              -809    }
              -810
              -811    public String getName() {
              -812        return commandName;
              -813    }
              -814
              -815    public ExceptionHandler getExceptionHandler() {
              -816        return exceptionHandler;
              -817    }
              -818
              -819    public BaseCommand setExceptionHandler(ExceptionHandler exceptionHandler) {
              -820        this.exceptionHandler = exceptionHandler;
              -821        return this;
              -822    }
              -823
              -824    public RegisteredCommand getDefaultRegisteredCommand() {
              -825        return ACFUtil.getFirstElement(this.subCommands.get(DEFAULT));
              -826    }
              -827
              -828    public String setContextFlags(Class<?> cls, String flags) {
              -829        return this.contextFlags.put(cls, flags);
              -830    }
              -831
              -832    public String getContextFlags(Class<?> cls) {
              -833        return this.contextFlags.get(cls);
              -834    }
              -835
              -836    public List<RegisteredCommand> getRegisteredCommands() {
              -837        List<RegisteredCommand> registeredCommands = new ArrayList<>();
              -838        registeredCommands.addAll(this.subCommands.values());
              -839        return registeredCommands;
              -840    }
              -841}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.CommandRouter.RouteSearch;
              +027import co.aikar.commands.annotation.CatchAll;
              +028import co.aikar.commands.annotation.CatchUnknown;
              +029import co.aikar.commands.annotation.CommandAlias;
              +030import co.aikar.commands.annotation.CommandPermission;
              +031import co.aikar.commands.annotation.Conditions;
              +032import co.aikar.commands.annotation.Default;
              +033import co.aikar.commands.annotation.Description;
              +034import co.aikar.commands.annotation.HelpCommand;
              +035import co.aikar.commands.annotation.PreCommand;
              +036import co.aikar.commands.annotation.Subcommand;
              +037import co.aikar.commands.annotation.UnknownHandler;
              +038import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              +039import com.google.common.collect.HashMultimap;
              +040import com.google.common.collect.SetMultimap;
              +041import org.jetbrains.annotations.Nullable;
              +042
              +043import java.lang.reflect.Constructor;
              +044import java.lang.reflect.InvocationTargetException;
              +045import java.lang.reflect.Method;
              +046import java.lang.reflect.Parameter;
              +047import java.util.ArrayList;
              +048import java.util.Arrays;
              +049import java.util.Collections;
              +050import java.util.HashMap;
              +051import java.util.HashSet;
              +052import java.util.LinkedHashSet;
              +053import java.util.List;
              +054import java.util.Locale;
              +055import java.util.Map;
              +056import java.util.Objects;
              +057import java.util.Set;
              +058import java.util.Stack;
              +059import java.util.stream.Collectors;
              +060import java.util.stream.Stream;
              +061
              +062/**
              +063 * A Base command is defined as a command group of related commands.
              +064 * A BaseCommand does not imply nor enforce that they use the same root command.
              +065 * <p>
              +066 * It is up to the end user how to organize their command. you could use 1 base command per
              +067 * command in your application.
              +068 * <p>
              +069 * Optionally (and encouraged), you can use the base command to represent a root command, and
              +070 * then each actionable command is a sub command
              +071 */
              +072
              +073public abstract class BaseCommand {
              +074
              +075    /**
              +076     * This is a field which contains the magic key in the {@link #subCommands} map for the method to catch any unknown
              +077     * argument to command states.
              +078     */
              +079    static final String CATCHUNKNOWN = "__catchunknown";
              +080    /**
              +081     * This is a field which contains the magic key in the {@link #subCommands} map for the method which is default for the
              +082     * entire base command.
              +083     */
              +084    static final String DEFAULT = "__default";
              +085
              +086    /**
              +087     * A map of all the registered commands for this base command, keyed to each potential subcommand to access it.
              +088     */
              +089    final SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
              +090    final Set<BaseCommand> subScopes = new HashSet<>();
              +091
              +092    /**
              +093     * A map of flags to pass to Context Resolution for every parameter of the type. This is like an automatic @Flags on each.
              +094     */
              +095    final Map<Class<?>, String> contextFlags = new HashMap<>();
              +096
              +097    /**
              +098     * What method was annoated with {@link PreCommand} to execute before commands.
              +099     */
              +100    @Nullable
              +101    private Method preCommandHandler;
              +102
              +103    /**
              +104     * What root command the user actually entered to access the currently executing command
              +105     */
              +106    @SuppressWarnings("WeakerAccess")
              +107    private String execLabel;
              +108    /**
              +109     * What subcommand the user actually entered to access the currently executing command
              +110     */
              +111    @SuppressWarnings("WeakerAccess")
              +112    private String execSubcommand;
              +113    /**
              +114     * What arguments the user actually entered after the root command to access the currently executing command
              +115     */
              +116    @SuppressWarnings("WeakerAccess")
              +117    private String[] origArgs;
              +118
              +119    /**
              +120     * The manager this is registered to
              +121     */
              +122    CommandManager<?, ?, ?, ?, ?, ?> manager = null;
              +123
              +124    /**
              +125     * The command which owns this. This may be null if there are no owners.
              +126     */
              +127    BaseCommand parentCommand;
              +128    Map<String, RootCommand> registeredCommands = new HashMap<>();
              +129    /**
              +130     * The description of the command. This may be null if no description has been provided.
              +131     * Used for help documentation
              +132     */
              +133    @Nullable String description;
              +134    /**
              +135     * The name of the command. This may be null if no name has been provided.
              +136     */
              +137    @Nullable String commandName;
              +138    /**
              +139     * The permission of the command. This may be null if no permission has been provided.
              +140     */
              +141    @Nullable String permission;
              +142    /**
              +143     * The conditions of the command. This may be null if no conditions has been provided.
              +144     */
              +145    @Nullable String conditions;
              +146    /**
              +147     * Identifies if the command has an explicit help command annotated with {@link HelpCommand}
              +148     */
              +149    boolean hasHelpCommand;
              +150
              +151    /**
              +152     * The handler of all uncaught exceptions thrown by the user's command implementation.
              +153     */
              +154    private ExceptionHandler exceptionHandler = null;
              +155    /**
              +156     * The last operative context data of this command. This may be null if this command hasn't been run yet.
              +157     */
              +158    private final ThreadLocal<CommandOperationContext> lastCommandOperationContext = new ThreadLocal<>();
              +159    /**
              +160     * If a parent exists to this command, and it has  a Subcommand annotation, prefix all subcommands in this class with this
              +161     */
              +162    @Nullable
              +163    private String parentSubcommand;
              +164
              +165    /**
              +166     * The permissions of the command.
              +167     */
              +168    private final Set<String> permissions = new HashSet<>();
              +169
              +170    public BaseCommand() {
              +171    }
              +172
              +173    /**
              +174     * Constructor based defining of commands will be removed in the next version bump.
              +175     *
              +176     * @param cmd
              +177     * @deprecated Please switch to {@link CommandAlias} for defining all root commands.
              +178     */
              +179    @Deprecated
              +180    public BaseCommand(@Nullable String cmd) {
              +181        this.commandName = cmd;
              +182    }
              +183
              +184    /**
              +185     * Returns a reference to the last used CommandOperationContext.
              +186     * This method is ThreadLocal, in that it can only be used on a thread that has executed a command
              +187     *
              +188     * @return
              +189     */
              +190    public CommandOperationContext getLastCommandOperationContext() {
              +191        return lastCommandOperationContext.get();
              +192    }
              +193
              +194    /**
              +195     * Gets the root command name that the user actually typed
              +196     *
              +197     * @return Name
              +198     */
              +199    public String getExecCommandLabel() {
              +200        return execLabel;
              +201    }
              +202
              +203    /**
              +204     * Gets the actual sub command name the user typed
              +205     *
              +206     * @return Name
              +207     */
              +208    public String getExecSubcommand() {
              +209        return execSubcommand;
              +210    }
              +211
              +212    /**
              +213     * Gets the actual args in string form the user typed
              +214     *
              +215     * @return Args
              +216     */
              +217    public String[] getOrigArgs() {
              +218        return origArgs;
              +219    }
              +220
              +221    /**
              +222     * This should be called whenever the command gets registered.
              +223     * It sets all required fields correctly and injects dependencies.
              +224     *
              +225     * @param manager The manager to register as this command's owner and handler.
              +226     */
              +227    void onRegister(CommandManager manager) {
              +228        onRegister(manager, this.commandName);
              +229    }
              +230
              +231    /**
              +232     * This should be called whenever the command gets registered.
              +233     * It sets all required fields correctly and injects dependencies.
              +234     *
              +235     * @param manager The manager to register as this command's owner and handler.
              +236     * @param cmd     The command name to use register with.
              +237     */
              +238    private void onRegister(CommandManager manager, String cmd) {
              +239        manager.injectDependencies(this);
              +240        this.manager = manager;
              +241
              +242        final Annotations annotations = manager.getAnnotations();
              +243        final Class<? extends BaseCommand> self = this.getClass();
              +244
              +245        String[] cmdAliases = annotations.getAnnotationValues(self, CommandAlias.class, Annotations.REPLACEMENTS | Annotations.LOWERCASE | Annotations.NO_EMPTY);
              +246
              +247        if (cmd == null && cmdAliases != null) {
              +248            cmd = cmdAliases[0];
              +249        }
              +250
              +251        this.commandName = cmd != null ? cmd : self.getSimpleName().toLowerCase(Locale.ENGLISH);
              +252        this.permission = annotations.getAnnotationValue(self, CommandPermission.class, Annotations.REPLACEMENTS);
              +253        this.description = annotations.getAnnotationValue(self, Description.class, Annotations.NO_EMPTY | Annotations.REPLACEMENTS);
              +254        this.parentSubcommand = getParentSubcommand(self);
              +255        this.conditions = annotations.getAnnotationValue(self, Conditions.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              +256
              +257        computePermissions(); // Must be before any subcommands so they can inherit permissions
              +258        registerSubcommands();
              +259        registerSubclasses(cmd);
              +260
              +261        if (cmdAliases != null) {
              +262            Set<String> cmdList = new HashSet<>();
              +263            Collections.addAll(cmdList, cmdAliases);
              +264            cmdList.remove(cmd);
              +265            for (String cmdAlias : cmdList) {
              +266                register(cmdAlias, this);
              +267            }
              +268        }
              +269
              +270        if (cmd != null) {
              +271            register(cmd, this);
              +272        }
              +273    }
              +274
              +275    /**
              +276     * This recursively registers all subclasses of the command as subcommands, if they are of type {@link BaseCommand}.
              +277     *
              +278     * @param cmd The command name of this command.
              +279     */
              +280    private void registerSubclasses(String cmd) {
              +281        for (Class<?> clazz : this.getClass().getDeclaredClasses()) {
              +282            if (BaseCommand.class.isAssignableFrom(clazz)) {
              +283                try {
              +284                    BaseCommand subScope = null;
              +285                    Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
              +286                    for (Constructor<?> declaredConstructor : declaredConstructors) {
              +287
              +288                        declaredConstructor.setAccessible(true);
              +289                        Parameter[] parameters = declaredConstructor.getParameters();
              +290                        if (parameters.length == 1) {
              +291                            subScope = (BaseCommand) declaredConstructor.newInstance(this);
              +292                        } else {
              +293                            manager.log(LogLevel.INFO, "Found unusable constructor: " + declaredConstructor.getName() + "(" + Stream.of(parameters).map(p -> p.getType().getSimpleName() + " " + p.getName()).collect(Collectors.joining("<c2>,</c2> ")) + ")");
              +294                        }
              +295                    }
              +296                    if (subScope != null) {
              +297                        subScope.parentCommand = this;
              +298                        this.subScopes.add(subScope);
              +299                        subScope.onRegister(manager, cmd);
              +300                        this.subCommands.putAll(subScope.subCommands);
              +301                        this.registeredCommands.putAll(subScope.registeredCommands);
              +302                    } else {
              +303                        this.manager.log(LogLevel.ERROR, "Could not find a subcommand ctor for " + clazz.getName());
              +304                    }
              +305                } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
              +306                    this.manager.log(LogLevel.ERROR, "Error registering subclass", e);
              +307                }
              +308            }
              +309        }
              +310    }
              +311
              +312    /**
              +313     * This registers all subcommands of the command.
              +314     */
              +315    private void registerSubcommands() {
              +316        final Annotations annotations = manager.getAnnotations();
              +317        boolean foundCatchUnknown = false;
              +318        boolean isParentEmpty = parentSubcommand == null || parentSubcommand.isEmpty();
              +319        Set<Method> methods = new LinkedHashSet<>();
              +320        Collections.addAll(methods, this.getClass().getDeclaredMethods());
              +321        Collections.addAll(methods, this.getClass().getMethods());
              +322
              +323        for (Method method : methods) {
              +324            method.setAccessible(true);
              +325            String sublist = null;
              +326            String sub = getSubcommandValue(method);
              +327            final String helpCommand = annotations.getAnnotationValue(method, HelpCommand.class, Annotations.NOTHING);
              +328            final String commandAliases = annotations.getAnnotationValue(method, CommandAlias.class, Annotations.NOTHING);
              +329
              +330            if (annotations.hasAnnotation(method, Default.class)) {
              +331                if (!isParentEmpty) {
              +332                    sub = parentSubcommand;
              +333                } else {
              +334                    registerSubcommand(method, DEFAULT);
              +335                }
              +336            }
              +337
              +338            if (sub != null) {
              +339                sublist = sub;
              +340            } else if (commandAliases != null) {
              +341                sublist = commandAliases;
              +342            } else if (helpCommand != null) {
              +343                sublist = helpCommand;
              +344                hasHelpCommand = true;
              +345            }
              +346
              +347            boolean preCommand = annotations.hasAnnotation(method, PreCommand.class);
              +348            boolean hasCatchUnknown = annotations.hasAnnotation(method, CatchUnknown.class) ||
              +349                    annotations.hasAnnotation(method, CatchAll.class) ||
              +350                    annotations.hasAnnotation(method, UnknownHandler.class);
              +351
              +352            if (hasCatchUnknown || (!foundCatchUnknown && helpCommand != null)) {
              +353                if (!foundCatchUnknown) {
              +354                    if (hasCatchUnknown) {
              +355                        this.subCommands.get(CATCHUNKNOWN).clear();
              +356                        foundCatchUnknown = true;
              +357                    }
              +358                    registerSubcommand(method, CATCHUNKNOWN);
              +359                } else {
              +360                    ACFUtil.sneaky(new IllegalStateException("Multiple @CatchUnknown/@HelpCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName()));
              +361                }
              +362            } else if (preCommand) {
              +363                if (this.preCommandHandler == null) {
              +364                    this.preCommandHandler = method;
              +365                } else {
              +366                    ACFUtil.sneaky(new IllegalStateException("Multiple @PreCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName()));
              +367                }
              +368            }
              +369            if (Objects.equals(method.getDeclaringClass(), this.getClass()) && sublist != null) {
              +370                registerSubcommand(method, sublist);
              +371            }
              +372        }
              +373    }
              +374
              +375    /**
              +376     * This registers all the permissions required to execute this command.
              +377     */
              +378    private void computePermissions() {
              +379        this.permissions.clear();
              +380        if (this.permission != null && !this.permission.isEmpty()) {
              +381            this.permissions.addAll(Arrays.asList(ACFPatterns.COMMA.split(this.permission)));
              +382        }
              +383        if (this.parentCommand != null) {
              +384            this.permissions.addAll(this.parentCommand.getRequiredPermissions());
              +385        }
              +386        this.subCommands.values().forEach(RegisteredCommand::computePermissions);
              +387        this.subScopes.forEach(BaseCommand::computePermissions);
              +388    }
              +389
              +390    /**
              +391     * Gets the subcommand name of the method given.
              +392     *
              +393     * @param method The method to check.
              +394     * @return The name of the subcommand. It returns null if the input doesn't have {@link Subcommand} attached.
              +395     */
              +396    private String getSubcommandValue(Method method) {
              +397        final String sub = manager.getAnnotations().getAnnotationValue(method, Subcommand.class, Annotations.NOTHING);
              +398        if (sub == null) {
              +399            return null;
              +400        }
              +401        Class<?> clazz = method.getDeclaringClass();
              +402        String parent = getParentSubcommand(clazz);
              +403        return parent == null || parent.isEmpty() ? sub : parent + " " + sub;
              +404    }
              +405
              +406    private String getParentSubcommand(Class<?> clazz) {
              +407        List<String> subList = new ArrayList<>();
              +408        while (clazz != null) {
              +409            String sub = manager.getAnnotations().getAnnotationValue(clazz, Subcommand.class, Annotations.NOTHING);
              +410            if (sub != null) {
              +411                subList.add(sub);
              +412            }
              +413            clazz = clazz.getEnclosingClass();
              +414        }
              +415        Collections.reverse(subList);
              +416        return ACFUtil.join(subList, " ");
              +417    }
              +418
              +419    /**
              +420     * Registers the given {@link BaseCommand cmd} as a child of the {@link RootCommand} linked to the name given.
              +421     *
              +422     * @param name Name of the parent to cmd.
              +423     * @param cmd  The {@link BaseCommand} to add as a child to the {@link RootCommand} owned name field.
              +424     */
              +425    private void register(String name, BaseCommand cmd) {
              +426        String nameLower = name.toLowerCase(Locale.ENGLISH);
              +427        RootCommand rootCommand = manager.obtainRootCommand(nameLower);
              +428        rootCommand.addChild(cmd);
              +429
              +430        this.registeredCommands.put(nameLower, rootCommand);
              +431    }
              +432
              +433    /**
              +434     * Registers the given {@link Method} as a subcommand.
              +435     *
              +436     * @param method     The method to register as a subcommand.
              +437     * @param subCommand The subcommand's name(s).
              +438     */
              +439    private void registerSubcommand(Method method, String subCommand) {
              +440        subCommand = manager.getCommandReplacements().replace(subCommand.toLowerCase(Locale.ENGLISH));
              +441        final String[] subCommandParts = ACFPatterns.SPACE.split(subCommand);
              +442        // Must run getSubcommandPossibility BEFORE we rewrite it just after this.
              +443        Set<String> cmdList = getSubCommandPossibilityList(subCommandParts);
              +444
              +445        // Strip pipes off for auto complete addition
              +446        for (int i = 0; i < subCommandParts.length; i++) {
              +447            String[] split = ACFPatterns.PIPE.split(subCommandParts[i]);
              +448            if (split.length == 0 || split[0].isEmpty()) {
              +449                throw new IllegalArgumentException("Invalid @Subcommand configuration for " + method.getName() + " - parts can not start with | or be empty");
              +450            }
              +451            subCommandParts[i] = split[0];
              +452        }
              +453        String prefSubCommand = ApacheCommonsLangUtil.join(subCommandParts, " ");
              +454        final String[] aliasNames = manager.getAnnotations().getAnnotationValues(method, CommandAlias.class, Annotations.REPLACEMENTS | Annotations.LOWERCASE);
              +455
              +456        String cmdName = aliasNames != null ? aliasNames[0] : this.commandName + " ";
              +457        RegisteredCommand cmd = manager.createRegisteredCommand(this, cmdName, method, prefSubCommand);
              +458
              +459        for (String subcmd : cmdList) {
              +460            subCommands.put(subcmd, cmd);
              +461        }
              +462        cmd.addSubcommands(cmdList);
              +463
              +464        if (aliasNames != null) {
              +465            for (String name : aliasNames) {
              +466                register(name, new ForwardingCommand(this, cmd, subCommandParts));
              +467            }
              +468        }
              +469    }
              +470
              +471    /**
              +472     * Takes a string like "foo|bar baz|qux" and generates a list of
              +473     * - foo baz
              +474     * - foo qux
              +475     * - bar baz
              +476     * - bar qux
              +477     * <p>
              +478     * For every possible sub command combination
              +479     *
              +480     * @param subCommandParts
              +481     * @return List of all sub command possibilities
              +482     */
              +483    private static Set<String> getSubCommandPossibilityList(String[] subCommandParts) {
              +484        int i = 0;
              +485        Set<String> current = null;
              +486        while (true) {
              +487            Set<String> newList = new HashSet<>();
              +488
              +489            if (i < subCommandParts.length) {
              +490                for (String s1 : ACFPatterns.PIPE.split(subCommandParts[i])) {
              +491                    if (current != null) {
              +492                        newList.addAll(current.stream().map(s -> s + " " + s1).collect(Collectors.toList()));
              +493                    } else {
              +494                        newList.add(s1);
              +495                    }
              +496                }
              +497            }
              +498
              +499            if (i + 1 < subCommandParts.length) {
              +500                current = newList;
              +501                i = i + 1;
              +502                continue;
              +503            }
              +504
              +505            return newList;
              +506        }
              +507    }
              +508
              +509    void execute(CommandIssuer issuer, CommandRouter.CommandRouteResult command) {
              +510        try {
              +511            CommandOperationContext commandContext = preCommandOperation(issuer, command.commandLabel, command.args, false);
              +512            execSubcommand = command.subcommand;
              +513            executeCommand(commandContext, issuer, command.args, command.cmd);
              +514        } finally {
              +515            postCommandOperation();
              +516        }
              +517    }
              +518
              +519    /**
              +520     * This is ran after any command operation has been performed.
              +521     */
              +522    private void postCommandOperation() {
              +523        CommandManager.commandOperationContext.get().pop();
              +524        execSubcommand = null;
              +525        execLabel = null;
              +526        origArgs = new String[]{};
              +527    }
              +528
              +529    /**
              +530     * This is ran before any command operation has been performed.
              +531     *
              +532     * @param issuer       The user who executed the command.
              +533     * @param commandLabel The label the user used to execute the command. This is not the command name, but their input.
              +534     *                     When there is multiple aliases, this is which alias was used
              +535     * @param args         The arguments passed to the command when executing it.
              +536     * @param isAsync      Whether the command is executed off of the main thread.
              +537     * @return The context which is being registered to the {@link CommandManager}'s {@link
              +538     * CommandManager#commandOperationContext thread local stack}.
              +539     */
              +540    private CommandOperationContext preCommandOperation(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) {
              +541        Stack<CommandOperationContext> contexts = CommandManager.commandOperationContext.get();
              +542        CommandOperationContext context = this.manager.createCommandOperationContext(this, issuer, commandLabel, args, isAsync);
              +543        contexts.push(context);
              +544        lastCommandOperationContext.set(context);
              +545        execSubcommand = null;
              +546        execLabel = commandLabel;
              +547        origArgs = args;
              +548        return context;
              +549    }
              +550
              +551    /**
              +552     * Gets the current command issuer.
              +553     *
              +554     * @return The current command issuer.
              +555     */
              +556    public CommandIssuer getCurrentCommandIssuer() {
              +557        return CommandManager.getCurrentCommandIssuer();
              +558    }
              +559
              +560    /**
              +561     * Gets the current command manager.
              +562     *
              +563     * @return The current command manager.
              +564     */
              +565    public CommandManager getCurrentCommandManager() {
              +566        return CommandManager.getCurrentCommandManager();
              +567    }
              +568
              +569    private void executeCommand(CommandOperationContext commandOperationContext,
              +570                                CommandIssuer issuer, String[] args, RegisteredCommand cmd) {
              +571        if (cmd.hasPermission(issuer)) {
              +572            commandOperationContext.setRegisteredCommand(cmd);
              +573            if (checkPrecommand(commandOperationContext, cmd, issuer, args)) {
              +574                return;
              +575            }
              +576            List<String> sargs = Arrays.asList(args);
              +577            cmd.invoke(issuer, sargs, commandOperationContext);
              +578        } else {
              +579            issuer.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED);
              +580        }
              +581    }
              +582
              +583    /**
              +584     * Please use command conditions for restricting execution
              +585     *
              +586     * @param issuer
              +587     * @param cmd
              +588     * @return
              +589     * @deprecated See {@link CommandConditions}
              +590     */
              +591    @SuppressWarnings("DeprecatedIsStillUsed")
              +592    @Deprecated
              +593    public boolean canExecute(CommandIssuer issuer, RegisteredCommand<?> cmd) {
              +594        return true;
              +595    }
              +596
              +597    /**
              +598     * Gets tab completed data from the given command from the user.
              +599     *
              +600     * @param issuer       The user who executed the tabcomplete.
              +601     * @param commandLabel The label which is being used by the user.
              +602     * @param args         The arguments the user has typed so far.
              +603     * @return All possibilities in the tab complete.
              +604     */
              +605    public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args) {
              +606        return tabComplete(issuer, commandLabel, args, false);
              +607    }
              +608
              +609    /**
              +610     * Gets the tab complete suggestions from a given command. This will automatically find anything
              +611     * which is valid for the specified command through the command's implementation.
              +612     *
              +613     * @param issuer       The issuer of the command.
              +614     * @param commandLabel The command name as entered by the user instead of the ACF registered name.
              +615     * @param args         All arguments entered by the user.
              +616     * @param isAsync      Whether this is run off of the main thread.
              +617     * @return The possibilities to tab complete in no particular order.
              +618     */
              +619    @SuppressWarnings("WeakerAccess")
              +620    public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync)
              +621            throws IllegalArgumentException {
              +622        return tabComplete(issuer, manager.getRootCommand(commandLabel.toLowerCase(Locale.ENGLISH)), args, isAsync);
              +623    }
              +624
              +625    List<String> tabComplete(CommandIssuer issuer, RootCommand rootCommand, String[] args, boolean isAsync)
              +626            throws IllegalArgumentException {
              +627        if (args.length == 0) {
              +628            args = new String[]{""};
              +629        }
              +630        String commandLabel = rootCommand.getCommandName();
              +631        try {
              +632            CommandRouter router = manager.getRouter();
              +633
              +634            preCommandOperation(issuer, commandLabel, args, isAsync);
              +635
              +636            final RouteSearch search = router.routeCommand(rootCommand, commandLabel, args, true);
              +637
              +638            final List<String> cmds = new ArrayList<>();
              +639            if (search != null) {
              +640                CommandRouter.CommandRouteResult result = router.matchCommand(search, true);
              +641                if (result != null) {
              +642                    cmds.addAll(completeCommand(issuer, result.cmd, result.args, commandLabel, isAsync));
              +643                }
              +644            }
              +645
              +646            return filterTabComplete(args[args.length - 1], cmds);
              +647        } finally {
              +648            postCommandOperation();
              +649        }
              +650    }
              +651
              +652    /**
              +653     * Gets all subcommands which are possible to tabcomplete.
              +654     *
              +655     * @param issuer The command issuer.
              +656     * @param args
              +657     * @return
              +658     */
              +659    List<String> getCommandsForCompletion(CommandIssuer issuer, String[] args) {
              +660        final Set<String> cmds = new HashSet<>();
              +661        final int cmdIndex = Math.max(0, args.length - 1);
              +662        String argString = ApacheCommonsLangUtil.join(args, " ").toLowerCase(Locale.ENGLISH);
              +663        for (Map.Entry<String, RegisteredCommand> entry : subCommands.entries()) {
              +664            final String key = entry.getKey();
              +665            if (key.startsWith(argString) && !CATCHUNKNOWN.equals(key) && !DEFAULT.equals(key)) {
              +666                final RegisteredCommand value = entry.getValue();
              +667                if (!value.hasPermission(issuer) || value.isPrivate) {
              +668                    continue;
              +669                }
              +670
              +671                String[] split = ACFPatterns.SPACE.split(value.prefSubCommand);
              +672                cmds.add(split[cmdIndex]);
              +673            }
              +674        }
              +675        return new ArrayList<>(cmds);
              +676    }
              +677
              +678    /**
              +679     * Complete a command properly per issuer and input.
              +680     *
              +681     * @param issuer       The user who executed this.
              +682     * @param cmd          The command to be completed.
              +683     * @param args         All arguments given by the user.
              +684     * @param commandLabel The command name the user used.
              +685     * @param isAsync      Whether the command was executed async.
              +686     * @return All results to complete the command.
              +687     */
              +688    private List<String> completeCommand(CommandIssuer issuer, RegisteredCommand cmd, String[] args, String commandLabel, boolean isAsync) {
              +689        if (!cmd.hasPermission(issuer) || args.length == 0 || cmd.parameters.length == 0) {
              +690            return Collections.emptyList();
              +691        }
              +692
              +693        if (!cmd.parameters[cmd.parameters.length - 1].consumesRest && args.length > cmd.consumeInputResolvers) {
              +694            return Collections.emptyList();
              +695        }
              +696
              +697        List<String> cmds = manager.getCommandCompletions().of(cmd, issuer, args, isAsync);
              +698        return filterTabComplete(args[args.length - 1], cmds);
              +699    }
              +700
              +701    /**
              +702     * Gets the actual args in string form the user typed
              +703     * This returns a list of all tab complete options which are possible with the given argument and commands.
              +704     *
              +705     * @param arg  Argument which was pressed tab on.
              +706     * @param cmds The possibilities to return.
              +707     * @return All possible options. This may be empty.
              +708     */
              +709    private static List<String> filterTabComplete(String arg, List<String> cmds) {
              +710        return cmds.stream()
              +711                .distinct()
              +712                .filter(cmd -> cmd != null && (arg.isEmpty() || ApacheCommonsLangUtil.startsWithIgnoreCase(cmd, arg)))
              +713                .collect(Collectors.toList());
              +714    }
              +715
              +716    /**
              +717     * Executes the precommand and sees whether something is wrong. Ideally, you get false from this.
              +718     *
              +719     * @param commandOperationContext The context to use.
              +720     * @param cmd                     The command executed.
              +721     * @param issuer                  The issuer who executed the command.
              +722     * @param args                    The arguments the issuer provided.
              +723     * @return Whether something went wrong.
              +724     */
              +725    private boolean checkPrecommand(CommandOperationContext commandOperationContext, RegisteredCommand cmd, CommandIssuer issuer, String[] args) {
              +726        Method pre = this.preCommandHandler;
              +727        if (pre != null) {
              +728            try {
              +729                Class<?>[] types = pre.getParameterTypes();
              +730                Object[] parameters = new Object[pre.getParameterCount()];
              +731                for (int i = 0; i < parameters.length; i++) {
              +732                    Class<?> type = types[i];
              +733                    Object issuerObject = issuer.getIssuer();
              +734                    if (manager.isCommandIssuer(type) && type.isAssignableFrom(issuerObject.getClass())) {
              +735                        parameters[i] = issuerObject;
              +736                    } else if (CommandIssuer.class.isAssignableFrom(type)) {
              +737                        parameters[i] = issuer;
              +738                    } else if (RegisteredCommand.class.isAssignableFrom(type)) {
              +739                        parameters[i] = cmd;
              +740                    } else if (String[].class.isAssignableFrom((type))) {
              +741                        parameters[i] = args;
              +742                    } else {
              +743                        parameters[i] = null;
              +744                    }
              +745                }
              +746
              +747                return (boolean) pre.invoke(this, parameters);
              +748            } catch (IllegalAccessException | InvocationTargetException e) {
              +749                this.manager.log(LogLevel.ERROR, "Exception encountered while command pre-processing", e);
              +750            }
              +751        }
              +752        return false;
              +753    }
              +754
              +755    /**
              +756     * @deprecated Unstable API
              +757     */
              +758    @Deprecated
              +759    @UnstableAPI
              +760    public CommandHelp getCommandHelp() {
              +761        return manager.generateCommandHelp();
              +762    }
              +763
              +764    /**
              +765     * @deprecated Unstable API
              +766     */
              +767    @Deprecated
              +768    @UnstableAPI
              +769    public void showCommandHelp() {
              +770        getCommandHelp().showHelp();
              +771    }
              +772
              +773    public void help(Object issuer, String[] args) {
              +774        help(manager.getCommandIssuer(issuer), args);
              +775    }
              +776
              +777    public void help(CommandIssuer issuer, String[] args) {
              +778        issuer.sendMessage(MessageType.ERROR, MessageKeys.UNKNOWN_COMMAND);
              +779    }
              +780
              +781    public void doHelp(Object issuer, String... args) {
              +782        doHelp(manager.getCommandIssuer(issuer), args);
              +783    }
              +784
              +785    public void doHelp(CommandIssuer issuer, String... args) {
              +786        help(issuer, args);
              +787    }
              +788
              +789    public void showSyntax(CommandIssuer issuer, RegisteredCommand<?> cmd) {
              +790        issuer.sendMessage(MessageType.SYNTAX, MessageKeys.INVALID_SYNTAX,
              +791                "{command}", manager.getCommandPrefix(issuer) + cmd.command,
              +792                "{syntax}", cmd.syntaxText
              +793        );
              +794    }
              +795
              +796    public boolean hasPermission(Object issuer) {
              +797        return hasPermission(manager.getCommandIssuer(issuer));
              +798    }
              +799
              +800    public boolean hasPermission(CommandIssuer issuer) {
              +801        return this.manager.hasPermission(issuer, getRequiredPermissions());
              +802    }
              +803
              +804    public Set<String> getRequiredPermissions() {
              +805        return this.permissions;
              +806    }
              +807
              +808    public boolean requiresPermission(String permission) {
              +809        return getRequiredPermissions().contains(permission);
              +810    }
              +811
              +812    public String getName() {
              +813        return commandName;
              +814    }
              +815
              +816    public ExceptionHandler getExceptionHandler() {
              +817        return exceptionHandler;
              +818    }
              +819
              +820    public BaseCommand setExceptionHandler(ExceptionHandler exceptionHandler) {
              +821        this.exceptionHandler = exceptionHandler;
              +822        return this;
              +823    }
              +824
              +825    public RegisteredCommand getDefaultRegisteredCommand() {
              +826        return ACFUtil.getFirstElement(this.subCommands.get(DEFAULT));
              +827    }
              +828
              +829    public String setContextFlags(Class<?> cls, String flags) {
              +830        return this.contextFlags.put(cls, flags);
              +831    }
              +832
              +833    public String getContextFlags(Class<?> cls) {
              +834        return this.contextFlags.get(cls);
              +835    }
              +836
              +837    public List<RegisteredCommand> getRegisteredCommands() {
              +838        List<RegisteredCommand> registeredCommands = new ArrayList<>();
              +839        registeredCommands.addAll(this.subCommands.values());
              +840        return registeredCommands;
              +841    }
              +842}
               
               
               
              @@ -909,5 +911,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandCompletionContext.html b/docs/acf-core/src-html/co/aikar/commands/CommandCompletionContext.html index 331131f6..35360abf 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandCompletionContext.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandCompletionContext.html @@ -1,139 +1,141 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import java.util.Arrays;
              -027import java.util.HashMap;
              -028import java.util.List;
              -029import java.util.Map;
              -030
              -031public class CommandCompletionContext<I extends CommandIssuer> {
              -032    private final RegisteredCommand command;
              -033    protected final I issuer;
              -034    private final String input;
              -035    private final String config;
              -036    private final Map<String, String> configs = new HashMap<>();
              -037    private final List<String> args;
              -038
              -039    CommandCompletionContext(RegisteredCommand command, I issuer, String input, String config, String[] args) {
              -040        this.command = command;
              -041        this.issuer = issuer;
              -042        this.input = input;
              -043        if (config != null) {
              -044            String[] configs = ACFPatterns.COMMA.split(config);
              -045            for (String conf : configs) {
              -046                String[] confsplit = ACFPatterns.EQUALS.split(conf, 2);
              -047                this.configs.put(confsplit[0].toLowerCase(), confsplit.length > 1 ? confsplit[1] : null);
              -048            }
              -049            this.config = configs[0];
              -050        } else {
              -051            this.config = null;
              -052        }
              -053
              -054        this.args = Arrays.asList(args);
              -055    }
              -056
              -057    public Map<String, String> getConfigs() {
              -058        return configs;
              -059    }
              -060
              -061    public String getConfig(String key) {
              -062        return getConfig(key, null);
              -063    }
              -064
              -065    public String getConfig(String key, String def) {
              -066        return this.configs.getOrDefault(key.toLowerCase(), def);
              -067    }
              -068
              -069    public boolean hasConfig(String key) {
              -070        return this.configs.containsKey(key.toLowerCase());
              -071    }
              -072
              -073    public <T> T getContextValue(Class<? extends T> clazz) throws InvalidCommandArgument {
              -074        return getContextValue(clazz, null);
              -075    }
              -076
              -077    public <T> T getContextValue(Class<? extends T> clazz, Integer paramIdx) throws InvalidCommandArgument {
              -078        String name = null;
              -079        if (paramIdx != null) {
              -080            if (paramIdx >= command.parameters.length) {
              -081                throw new IllegalArgumentException("Param index is higher than number of parameters");
              -082            }
              -083            CommandParameter param = command.parameters[paramIdx];
              -084            Class<?> paramType = param.getType();
              -085            if (!clazz.isAssignableFrom(paramType)) {
              -086                throw new IllegalArgumentException(param.getName() + ":" + paramType.getName() + " can not satisfy " + clazz.getName());
              -087            }
              -088            name = param.getName();
              -089        } else {
              -090            CommandParameter[] parameters = command.parameters;
              -091            for (int i = 0; i < parameters.length; i++) {
              -092                final CommandParameter parameter = parameters[i];
              -093                if (clazz.isAssignableFrom(parameter.getType())) {
              -094                    paramIdx = i;
              -095                    name = parameter.getName();
              -096                    break;
              -097                }
              -098            }
              -099            if (paramIdx == null) {
              -100                throw new IllegalStateException("Can not find any parameter that can satisfy " + clazz.getName());
              -101            }
              -102        }
              -103        //noinspection unchecked
              -104        Map<String, Object> resolved = command.resolveContexts(issuer, args, args.size() - 1);
              -105        if (resolved == null || paramIdx > resolved.size()) {
              -106            ACFUtil.sneaky(new CommandCompletionTextLookupException());
              -107        }
              -108
              -109        //noinspection unchecked
              -110        return (T) resolved.get(name);
              -111    }
              -112
              -113    public CommandIssuer getIssuer() {
              -114        return issuer;
              -115    }
              -116
              -117    public String getInput() {
              -118        return input;
              -119    }
              -120
              -121    public String getConfig() {
              -122        return config;
              -123    }
              -124
              -125    public boolean isAsync() {
              -126        return CommandManager.getCurrentCommandOperationContext().isAsync();
              -127    }
              -128}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import java.util.Arrays;
              +027import java.util.HashMap;
              +028import java.util.List;
              +029import java.util.Locale;
              +030import java.util.Map;
              +031
              +032public class CommandCompletionContext<I extends CommandIssuer> {
              +033    private final RegisteredCommand command;
              +034    protected final I issuer;
              +035    private final String input;
              +036    private final String config;
              +037    private final Map<String, String> configs = new HashMap<>();
              +038    private final List<String> args;
              +039
              +040    CommandCompletionContext(RegisteredCommand command, I issuer, String input, String config, String[] args) {
              +041        this.command = command;
              +042        this.issuer = issuer;
              +043        this.input = input;
              +044        if (config != null) {
              +045            String[] configs = ACFPatterns.COMMA.split(config);
              +046            for (String conf : configs) {
              +047                String[] confsplit = ACFPatterns.EQUALS.split(conf, 2);
              +048                this.configs.put(confsplit[0].toLowerCase(Locale.ENGLISH), confsplit.length > 1 ? confsplit[1] : null);
              +049            }
              +050            this.config = configs[0];
              +051        } else {
              +052            this.config = null;
              +053        }
              +054
              +055        this.args = Arrays.asList(args);
              +056    }
              +057
              +058    public Map<String, String> getConfigs() {
              +059        return configs;
              +060    }
              +061
              +062    public String getConfig(String key) {
              +063        return getConfig(key, null);
              +064    }
              +065
              +066    public String getConfig(String key, String def) {
              +067        return this.configs.getOrDefault(key.toLowerCase(Locale.ENGLISH), def);
              +068    }
              +069
              +070    public boolean hasConfig(String key) {
              +071        return this.configs.containsKey(key.toLowerCase(Locale.ENGLISH));
              +072    }
              +073
              +074    public <T> T getContextValue(Class<? extends T> clazz) throws InvalidCommandArgument {
              +075        return getContextValue(clazz, null);
              +076    }
              +077
              +078    public <T> T getContextValue(Class<? extends T> clazz, Integer paramIdx) throws InvalidCommandArgument {
              +079        String name = null;
              +080        if (paramIdx != null) {
              +081            if (paramIdx >= command.parameters.length) {
              +082                throw new IllegalArgumentException("Param index is higher than number of parameters");
              +083            }
              +084            CommandParameter param = command.parameters[paramIdx];
              +085            Class<?> paramType = param.getType();
              +086            if (!clazz.isAssignableFrom(paramType)) {
              +087                throw new IllegalArgumentException(param.getName() + ":" + paramType.getName() + " can not satisfy " + clazz.getName());
              +088            }
              +089            name = param.getName();
              +090        } else {
              +091            CommandParameter[] parameters = command.parameters;
              +092            for (int i = 0; i < parameters.length; i++) {
              +093                final CommandParameter parameter = parameters[i];
              +094                if (clazz.isAssignableFrom(parameter.getType())) {
              +095                    paramIdx = i;
              +096                    name = parameter.getName();
              +097                    break;
              +098                }
              +099            }
              +100            if (paramIdx == null) {
              +101                throw new IllegalStateException("Can not find any parameter that can satisfy " + clazz.getName());
              +102            }
              +103        }
              +104        //noinspection unchecked
              +105        Map<String, Object> resolved = command.resolveContexts(issuer, args, args.size() - 1);
              +106        if (resolved == null || paramIdx > resolved.size()) {
              +107            ACFUtil.sneaky(new CommandCompletionTextLookupException());
              +108        }
              +109
              +110        //noinspection unchecked
              +111        return (T) resolved.get(name);
              +112    }
              +113
              +114    public CommandIssuer getIssuer() {
              +115        return issuer;
              +116    }
              +117
              +118    public String getInput() {
              +119        return input;
              +120    }
              +121
              +122    public String getConfig() {
              +123        return config;
              +124    }
              +125
              +126    public boolean isAsync() {
              +127        return CommandManager.getCurrentCommandOperationContext().isAsync();
              +128    }
              +129}
               
               
               
              @@ -196,5 +198,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.AsyncCommandCompletionHandler.html b/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.AsyncCommandCompletionHandler.html index f2dc2c4c..69176277 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.AsyncCommandCompletionHandler.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.AsyncCommandCompletionHandler.html @@ -1,320 +1,322 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              -027import org.jetbrains.annotations.NotNull;
              -028
              -029import java.util.ArrayList;
              -030import java.util.Arrays;
              -031import java.util.Collection;
              -032import java.util.Collections;
              -033import java.util.HashMap;
              -034import java.util.List;
              -035import java.util.Map;
              -036import java.util.function.Supplier;
              -037import java.util.stream.Collectors;
              -038import java.util.stream.IntStream;
              -039
              -040
              -041@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
              -042public class CommandCompletions<C extends CommandCompletionContext> {
              -043    private static final String DEFAULT_ENUM_ID = "@__defaultenum__";
              -044    private final CommandManager manager;
              -045    // TODO: use a CompletionProvider that can return a delegated Id or provide values such as enum support
              -046    private Map<String, CommandCompletionHandler> completionMap = new HashMap<>();
              -047    private Map<Class, String> defaultCompletions = new HashMap<>();
              -048
              -049    public CommandCompletions(CommandManager manager) {
              -050        this.manager = manager;
              -051        registerStaticCompletion("empty", Collections.emptyList());
              -052        registerStaticCompletion("nothing", Collections.emptyList());
              -053        registerStaticCompletion("timeunits", Arrays.asList("minutes", "hours", "days", "weeks", "months", "years"));
              -054        registerAsyncCompletion("range", (c) -> {
              -055            String config = c.getConfig();
              -056            if (config == null) {
              -057                return Collections.emptyList();
              -058            }
              -059            final String[] ranges = ACFPatterns.DASH.split(config);
              -060            int start;
              -061            int end;
              -062            if (ranges.length != 2) {
              -063                start = 0;
              -064                end = ACFUtil.parseInt(ranges[0], 0);
              -065            } else {
              -066                start = ACFUtil.parseInt(ranges[0], 0);
              -067                end = ACFUtil.parseInt(ranges[1], 0);
              -068            }
              -069            return IntStream.rangeClosed(start, end).mapToObj(Integer::toString).collect(Collectors.toList());
              -070        });
              -071    }
              -072
              -073    /**
              -074     * Registr a completion handler to provide command completions based on the user input.
              -075     *
              -076     * @param id
              -077     * @param handler
              -078     * @return
              -079     */
              -080    public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<C> handler) {
              -081        return this.completionMap.put(prepareCompletionId(id), handler);
              -082    }
              -083
              -084    /**
              -085     * Registr a completion handler to provide command completions based on the user input.
              -086     * This handler is declared to be safe to be executed asynchronously.
              -087     * <p>
              -088     * Not all platforms support this, so if the platform does not support asynchronous execution,
              -089     * your handler will be executed on the main thread.
              -090     * <p>
              -091     * Use this anytime your handler does not need to access state that is not considered thread safe.
              -092     * <p>
              -093     * Use context.isAsync() to determine if you are async or not.
              -094     *
              -095     * @param id
              -096     * @param handler
              -097     * @return
              -098     */
              -099    public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<C> handler) {
              -100        return this.completionMap.put(prepareCompletionId(id), handler);
              -101    }
              -102
              -103    /**
              -104     * Register a static list of command completions that will never change.
              -105     * Like @CommandCompletion, values are | (PIPE) separated.
              -106     * <p>
              -107     * Example: foo|bar|baz
              -108     *
              -109     * @param id
              -110     * @param list
              -111     * @return
              -112     */
              -113    public CommandCompletionHandler registerStaticCompletion(String id, String list) {
              -114        return registerStaticCompletion(id, ACFPatterns.PIPE.split(list));
              -115    }
              -116
              -117    /**
              -118     * Register a static list of command completions that will never change
              -119     *
              -120     * @param id
              -121     * @param completions
              -122     * @return
              -123     */
              -124    public CommandCompletionHandler registerStaticCompletion(String id, String[] completions) {
              -125        return registerStaticCompletion(id, Arrays.asList(completions));
              -126    }
              -127
              -128    /**
              -129     * Register a static list of command completions that will never change. The list is obtained from the supplier
              -130     * immediately as part of this method call.
              -131     *
              -132     * @param id
              -133     * @param supplier
              -134     * @return
              -135     */
              -136    public CommandCompletionHandler registerStaticCompletion(String id, Supplier<Collection<String>> supplier) {
              -137        return registerStaticCompletion(id, supplier.get());
              -138    }
              -139
              -140    /**
              -141     * Register a static list of command completions that will never change
              -142     *
              -143     * @param id
              -144     * @param completions
              -145     * @return
              -146     */
              -147    public CommandCompletionHandler registerStaticCompletion(String id, Collection<String> completions) {
              -148        return registerAsyncCompletion(id, x -> completions);
              -149    }
              -150
              -151    /**
              -152     * Registers a completion handler such as @players to default apply to all command parameters of the specified types
              -153     * <p>
              -154     * This enables automatic completion support for parameters without manually defining it for custom objects
              -155     *
              -156     * @param id
              -157     * @param classes
              -158     */
              -159    public void setDefaultCompletion(String id, Class... classes) {
              -160        // get completion with specified id
              -161        id = prepareCompletionId(id);
              -162        CommandCompletionHandler completion = completionMap.get(id);
              -163
              -164        if (completion == null) {
              -165            // Throw something because no completion with specified id
              -166            throw new IllegalStateException("Completion not registered for " + id);
              -167        }
              -168
              -169        for (Class clazz : classes) {
              -170            defaultCompletions.put(clazz, id);
              -171        }
              -172    }
              -173
              -174    @NotNull
              -175    private static String prepareCompletionId(String id) {
              -176        return (id.startsWith("@") ? "" : "@") + id.toLowerCase();
              -177    }
              -178
              -179    @NotNull
              -180    List<String> of(RegisteredCommand cmd, CommandIssuer sender, String[] args, boolean isAsync) {
              -181        String[] completions = ACFPatterns.SPACE.split(cmd.complete);
              -182        final int argIndex = args.length - 1;
              -183
              -184        String input = args[argIndex];
              -185
              -186        String completion = argIndex < completions.length ? completions[argIndex] : null;
              -187        if (completion == null || "*".equals(completion)) {
              -188            completion = findDefaultCompletion(cmd, args);
              -189        }
              -190
              -191        if (completion == null && completions.length > 0) {
              -192            String last = completions[completions.length - 1];
              -193            if (last.startsWith("repeat@")) {
              -194                completion = last;
              -195            } else if (argIndex >= completions.length && cmd.parameters[cmd.parameters.length - 1].consumesRest) {
              -196                completion = last;
              -197            }
              -198        }
              -199
              -200        if (completion == null) {
              -201            return Collections.singletonList(input);
              -202        }
              -203
              -204        return getCompletionValues(cmd, sender, completion, args, isAsync);
              -205    }
              -206
              -207    String findDefaultCompletion(RegisteredCommand cmd, String[] args) {
              -208        int i = 0;
              -209        for (CommandParameter param : cmd.parameters) {
              -210            if (param.canConsumeInput() && ++i == args.length) {
              -211                Class type = param.getType();
              -212                while (type != null) {
              -213                    String completion = this.defaultCompletions.get(type);
              -214                    if (completion != null) {
              -215                        return completion;
              -216                    }
              -217                    type = type.getSuperclass();
              -218                }
              -219                if (param.getType().isEnum()) {
              -220                    CommandOperationContext ctx = CommandManager.getCurrentCommandOperationContext();
              -221                    //noinspection unchecked
              -222                    ctx.enumCompletionValues = ACFUtil.enumNames((Class<? extends Enum<?>>) param.getType());
              -223                    return DEFAULT_ENUM_ID;
              -224                }
              -225                break;
              -226            }
              -227        }
              -228        return null;
              -229    }
              -230
              -231    List<String> getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) {
              -232        if (DEFAULT_ENUM_ID.equals(completion)) {
              -233            CommandOperationContext<?> ctx = CommandManager.getCurrentCommandOperationContext();
              -234            return ctx.enumCompletionValues;
              -235        }
              -236        boolean repeat = completion.startsWith("repeat@");
              -237        if (repeat) {
              -238            completion = completion.substring(6);
              -239        }
              -240        completion = manager.getCommandReplacements().replace(completion);
              -241
              -242        List<String> allCompletions = new ArrayList<>();
              -243        String input = args.length > 0 ? args[args.length - 1] : "";
              -244
              -245        for (String value : ACFPatterns.PIPE.split(completion)) {
              -246            String[] complete = ACFPatterns.COLONEQUALS.split(value, 2);
              -247            CommandCompletionHandler handler = this.completionMap.get(complete[0].toLowerCase());
              -248            if (handler != null) {
              -249                if (isAsync && !(handler instanceof AsyncCommandCompletionHandler)) {
              -250                    ACFUtil.sneaky(new SyncCompletionRequired());
              -251                    return null;
              -252                }
              -253                String config = complete.length == 1 ? null : complete[1];
              -254                CommandCompletionContext context = manager.createCompletionContext(command, sender, input, config, args);
              -255
              -256                try {
              -257                    //noinspection unchecked
              -258                    Collection<String> completions = handler.getCompletions(context);
              -259
              -260                    //Handle completions with more than one word:
              -261                    if (!repeat && completions != null
              -262                            && command.parameters[command.parameters.length - 1].consumesRest
              -263                            && args.length > ACFPatterns.SPACE.split(command.complete).length) {
              -264                        String start = String.join(" ", args);
              -265                        completions = completions.stream()
              -266                                .map(s -> {
              -267                                    if (s != null && s.split(" ").length >= args.length && ApacheCommonsLangUtil.startsWithIgnoreCase(s, start)) {
              -268                                        String[] completionArgs = s.split(" ");
              -269                                        return String.join(" ", Arrays.copyOfRange(completionArgs, args.length - 1, completionArgs.length));
              -270                                    } else {
              -271                                        return s;
              -272                                    }
              -273                                }).collect(Collectors.toList());
              -274                    }
              -275
              -276                    if (completions != null) {
              -277                        allCompletions.addAll(completions);
              -278                        continue;
              -279                    }
              -280                    //noinspection ConstantIfStatement,ConstantConditions
              -281                    if (false) { // Hack to fool compiler. since its sneakily thrown.
              -282                        throw new CommandCompletionTextLookupException();
              -283                    }
              -284                } catch (CommandCompletionTextLookupException ignored) {
              -285                    // This should only happen if some other feedback error occured.
              -286                } catch (Exception e) {
              -287                    command.handleException(sender, Arrays.asList(args), e);
              -288                }
              -289                // Something went wrong in lookup, fall back to input
              -290                return Collections.singletonList(input);
              -291            } else {
              -292                // Plaintext value
              -293                allCompletions.add(value);
              -294            }
              -295        }
              -296        return allCompletions;
              -297    }
              -298
              -299    public interface CommandCompletionHandler<C extends CommandCompletionContext> {
              -300        Collection<String> getCompletions(C context) throws InvalidCommandArgument;
              -301    }
              -302
              -303    public interface AsyncCommandCompletionHandler<C extends CommandCompletionContext> extends CommandCompletionHandler<C> {
              -304    }
              -305
              -306    public static class SyncCompletionRequired extends RuntimeException {
              -307    }
              -308
              -309}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              +027import org.jetbrains.annotations.NotNull;
              +028
              +029import java.util.ArrayList;
              +030import java.util.Arrays;
              +031import java.util.Collection;
              +032import java.util.Collections;
              +033import java.util.HashMap;
              +034import java.util.List;
              +035import java.util.Locale;
              +036import java.util.Map;
              +037import java.util.function.Supplier;
              +038import java.util.stream.Collectors;
              +039import java.util.stream.IntStream;
              +040
              +041
              +042@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
              +043public class CommandCompletions<C extends CommandCompletionContext> {
              +044    private static final String DEFAULT_ENUM_ID = "@__defaultenum__";
              +045    private final CommandManager manager;
              +046    // TODO: use a CompletionProvider that can return a delegated Id or provide values such as enum support
              +047    private Map<String, CommandCompletionHandler> completionMap = new HashMap<>();
              +048    private Map<Class, String> defaultCompletions = new HashMap<>();
              +049
              +050    public CommandCompletions(CommandManager manager) {
              +051        this.manager = manager;
              +052        registerStaticCompletion("empty", Collections.emptyList());
              +053        registerStaticCompletion("nothing", Collections.emptyList());
              +054        registerStaticCompletion("timeunits", Arrays.asList("minutes", "hours", "days", "weeks", "months", "years"));
              +055        registerAsyncCompletion("range", (c) -> {
              +056            String config = c.getConfig();
              +057            if (config == null) {
              +058                return Collections.emptyList();
              +059            }
              +060            final String[] ranges = ACFPatterns.DASH.split(config);
              +061            int start;
              +062            int end;
              +063            if (ranges.length != 2) {
              +064                start = 0;
              +065                end = ACFUtil.parseInt(ranges[0], 0);
              +066            } else {
              +067                start = ACFUtil.parseInt(ranges[0], 0);
              +068                end = ACFUtil.parseInt(ranges[1], 0);
              +069            }
              +070            return IntStream.rangeClosed(start, end).mapToObj(Integer::toString).collect(Collectors.toList());
              +071        });
              +072    }
              +073
              +074    /**
              +075     * Registr a completion handler to provide command completions based on the user input.
              +076     *
              +077     * @param id
              +078     * @param handler
              +079     * @return
              +080     */
              +081    public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<C> handler) {
              +082        return this.completionMap.put(prepareCompletionId(id), handler);
              +083    }
              +084
              +085    /**
              +086     * Registr a completion handler to provide command completions based on the user input.
              +087     * This handler is declared to be safe to be executed asynchronously.
              +088     * <p>
              +089     * Not all platforms support this, so if the platform does not support asynchronous execution,
              +090     * your handler will be executed on the main thread.
              +091     * <p>
              +092     * Use this anytime your handler does not need to access state that is not considered thread safe.
              +093     * <p>
              +094     * Use context.isAsync() to determine if you are async or not.
              +095     *
              +096     * @param id
              +097     * @param handler
              +098     * @return
              +099     */
              +100    public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<C> handler) {
              +101        return this.completionMap.put(prepareCompletionId(id), handler);
              +102    }
              +103
              +104    /**
              +105     * Register a static list of command completions that will never change.
              +106     * Like @CommandCompletion, values are | (PIPE) separated.
              +107     * <p>
              +108     * Example: foo|bar|baz
              +109     *
              +110     * @param id
              +111     * @param list
              +112     * @return
              +113     */
              +114    public CommandCompletionHandler registerStaticCompletion(String id, String list) {
              +115        return registerStaticCompletion(id, ACFPatterns.PIPE.split(list));
              +116    }
              +117
              +118    /**
              +119     * Register a static list of command completions that will never change
              +120     *
              +121     * @param id
              +122     * @param completions
              +123     * @return
              +124     */
              +125    public CommandCompletionHandler registerStaticCompletion(String id, String[] completions) {
              +126        return registerStaticCompletion(id, Arrays.asList(completions));
              +127    }
              +128
              +129    /**
              +130     * Register a static list of command completions that will never change. The list is obtained from the supplier
              +131     * immediately as part of this method call.
              +132     *
              +133     * @param id
              +134     * @param supplier
              +135     * @return
              +136     */
              +137    public CommandCompletionHandler registerStaticCompletion(String id, Supplier<Collection<String>> supplier) {
              +138        return registerStaticCompletion(id, supplier.get());
              +139    }
              +140
              +141    /**
              +142     * Register a static list of command completions that will never change
              +143     *
              +144     * @param id
              +145     * @param completions
              +146     * @return
              +147     */
              +148    public CommandCompletionHandler registerStaticCompletion(String id, Collection<String> completions) {
              +149        return registerAsyncCompletion(id, x -> completions);
              +150    }
              +151
              +152    /**
              +153     * Registers a completion handler such as @players to default apply to all command parameters of the specified types
              +154     * <p>
              +155     * This enables automatic completion support for parameters without manually defining it for custom objects
              +156     *
              +157     * @param id
              +158     * @param classes
              +159     */
              +160    public void setDefaultCompletion(String id, Class... classes) {
              +161        // get completion with specified id
              +162        id = prepareCompletionId(id);
              +163        CommandCompletionHandler completion = completionMap.get(id);
              +164
              +165        if (completion == null) {
              +166            // Throw something because no completion with specified id
              +167            throw new IllegalStateException("Completion not registered for " + id);
              +168        }
              +169
              +170        for (Class clazz : classes) {
              +171            defaultCompletions.put(clazz, id);
              +172        }
              +173    }
              +174
              +175    @NotNull
              +176    private static String prepareCompletionId(String id) {
              +177        return (id.startsWith("@") ? "" : "@") + id.toLowerCase(Locale.ENGLISH);
              +178    }
              +179
              +180    @NotNull
              +181    List<String> of(RegisteredCommand cmd, CommandIssuer sender, String[] args, boolean isAsync) {
              +182        String[] completions = ACFPatterns.SPACE.split(cmd.complete);
              +183        final int argIndex = args.length - 1;
              +184
              +185        String input = args[argIndex];
              +186
              +187        String completion = argIndex < completions.length ? completions[argIndex] : null;
              +188        if (completion == null || "*".equals(completion)) {
              +189            completion = findDefaultCompletion(cmd, args);
              +190        }
              +191
              +192        if (completion == null && completions.length > 0) {
              +193            String last = completions[completions.length - 1];
              +194            if (last.startsWith("repeat@")) {
              +195                completion = last;
              +196            } else if (argIndex >= completions.length && cmd.parameters[cmd.parameters.length - 1].consumesRest) {
              +197                completion = last;
              +198            }
              +199        }
              +200
              +201        if (completion == null) {
              +202            return Collections.singletonList(input);
              +203        }
              +204
              +205        return getCompletionValues(cmd, sender, completion, args, isAsync);
              +206    }
              +207
              +208    String findDefaultCompletion(RegisteredCommand cmd, String[] args) {
              +209        int i = 0;
              +210        for (CommandParameter param : cmd.parameters) {
              +211            if (param.canConsumeInput() && ++i == args.length) {
              +212                Class type = param.getType();
              +213                while (type != null) {
              +214                    String completion = this.defaultCompletions.get(type);
              +215                    if (completion != null) {
              +216                        return completion;
              +217                    }
              +218                    type = type.getSuperclass();
              +219                }
              +220                if (param.getType().isEnum()) {
              +221                    CommandOperationContext ctx = CommandManager.getCurrentCommandOperationContext();
              +222                    //noinspection unchecked
              +223                    ctx.enumCompletionValues = ACFUtil.enumNames((Class<? extends Enum<?>>) param.getType());
              +224                    return DEFAULT_ENUM_ID;
              +225                }
              +226                break;
              +227            }
              +228        }
              +229        return null;
              +230    }
              +231
              +232    List<String> getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) {
              +233        if (DEFAULT_ENUM_ID.equals(completion)) {
              +234            CommandOperationContext<?> ctx = CommandManager.getCurrentCommandOperationContext();
              +235            return ctx.enumCompletionValues;
              +236        }
              +237        boolean repeat = completion.startsWith("repeat@");
              +238        if (repeat) {
              +239            completion = completion.substring(6);
              +240        }
              +241        completion = manager.getCommandReplacements().replace(completion);
              +242
              +243        List<String> allCompletions = new ArrayList<>();
              +244        String input = args.length > 0 ? args[args.length - 1] : "";
              +245
              +246        for (String value : ACFPatterns.PIPE.split(completion)) {
              +247            String[] complete = ACFPatterns.COLONEQUALS.split(value, 2);
              +248            CommandCompletionHandler handler = this.completionMap.get(complete[0].toLowerCase(Locale.ENGLISH));
              +249            if (handler != null) {
              +250                if (isAsync && !(handler instanceof AsyncCommandCompletionHandler)) {
              +251                    ACFUtil.sneaky(new SyncCompletionRequired());
              +252                    return null;
              +253                }
              +254                String config = complete.length == 1 ? null : complete[1];
              +255                CommandCompletionContext context = manager.createCompletionContext(command, sender, input, config, args);
              +256
              +257                try {
              +258                    //noinspection unchecked
              +259                    Collection<String> completions = handler.getCompletions(context);
              +260
              +261                    //Handle completions with more than one word:
              +262                    if (!repeat && completions != null
              +263                            && command.parameters[command.parameters.length - 1].consumesRest
              +264                            && args.length > ACFPatterns.SPACE.split(command.complete).length) {
              +265                        String start = String.join(" ", args);
              +266                        completions = completions.stream()
              +267                                .map(s -> {
              +268                                    if (s != null && s.split(" ").length >= args.length && ApacheCommonsLangUtil.startsWithIgnoreCase(s, start)) {
              +269                                        String[] completionArgs = s.split(" ");
              +270                                        return String.join(" ", Arrays.copyOfRange(completionArgs, args.length - 1, completionArgs.length));
              +271                                    } else {
              +272                                        return s;
              +273                                    }
              +274                                }).collect(Collectors.toList());
              +275                    }
              +276
              +277                    if (completions != null) {
              +278                        allCompletions.addAll(completions);
              +279                        continue;
              +280                    }
              +281                    //noinspection ConstantIfStatement,ConstantConditions
              +282                    if (false) { // Hack to fool compiler. since its sneakily thrown.
              +283                        throw new CommandCompletionTextLookupException();
              +284                    }
              +285                } catch (CommandCompletionTextLookupException ignored) {
              +286                    // This should only happen if some other feedback error occured.
              +287                } catch (Exception e) {
              +288                    command.handleException(sender, Arrays.asList(args), e);
              +289                }
              +290                // Something went wrong in lookup, fall back to input
              +291                return Collections.singletonList(input);
              +292            } else {
              +293                // Plaintext value
              +294                allCompletions.add(value);
              +295            }
              +296        }
              +297        return allCompletions;
              +298    }
              +299
              +300    public interface CommandCompletionHandler<C extends CommandCompletionContext> {
              +301        Collection<String> getCompletions(C context) throws InvalidCommandArgument;
              +302    }
              +303
              +304    public interface AsyncCommandCompletionHandler<C extends CommandCompletionContext> extends CommandCompletionHandler<C> {
              +305    }
              +306
              +307    public static class SyncCompletionRequired extends RuntimeException {
              +308    }
              +309
              +310}
               
               
               
              @@ -377,5 +379,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.CommandCompletionHandler.html b/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.CommandCompletionHandler.html index f2dc2c4c..69176277 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.CommandCompletionHandler.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.CommandCompletionHandler.html @@ -1,320 +1,322 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              -027import org.jetbrains.annotations.NotNull;
              -028
              -029import java.util.ArrayList;
              -030import java.util.Arrays;
              -031import java.util.Collection;
              -032import java.util.Collections;
              -033import java.util.HashMap;
              -034import java.util.List;
              -035import java.util.Map;
              -036import java.util.function.Supplier;
              -037import java.util.stream.Collectors;
              -038import java.util.stream.IntStream;
              -039
              -040
              -041@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
              -042public class CommandCompletions<C extends CommandCompletionContext> {
              -043    private static final String DEFAULT_ENUM_ID = "@__defaultenum__";
              -044    private final CommandManager manager;
              -045    // TODO: use a CompletionProvider that can return a delegated Id or provide values such as enum support
              -046    private Map<String, CommandCompletionHandler> completionMap = new HashMap<>();
              -047    private Map<Class, String> defaultCompletions = new HashMap<>();
              -048
              -049    public CommandCompletions(CommandManager manager) {
              -050        this.manager = manager;
              -051        registerStaticCompletion("empty", Collections.emptyList());
              -052        registerStaticCompletion("nothing", Collections.emptyList());
              -053        registerStaticCompletion("timeunits", Arrays.asList("minutes", "hours", "days", "weeks", "months", "years"));
              -054        registerAsyncCompletion("range", (c) -> {
              -055            String config = c.getConfig();
              -056            if (config == null) {
              -057                return Collections.emptyList();
              -058            }
              -059            final String[] ranges = ACFPatterns.DASH.split(config);
              -060            int start;
              -061            int end;
              -062            if (ranges.length != 2) {
              -063                start = 0;
              -064                end = ACFUtil.parseInt(ranges[0], 0);
              -065            } else {
              -066                start = ACFUtil.parseInt(ranges[0], 0);
              -067                end = ACFUtil.parseInt(ranges[1], 0);
              -068            }
              -069            return IntStream.rangeClosed(start, end).mapToObj(Integer::toString).collect(Collectors.toList());
              -070        });
              -071    }
              -072
              -073    /**
              -074     * Registr a completion handler to provide command completions based on the user input.
              -075     *
              -076     * @param id
              -077     * @param handler
              -078     * @return
              -079     */
              -080    public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<C> handler) {
              -081        return this.completionMap.put(prepareCompletionId(id), handler);
              -082    }
              -083
              -084    /**
              -085     * Registr a completion handler to provide command completions based on the user input.
              -086     * This handler is declared to be safe to be executed asynchronously.
              -087     * <p>
              -088     * Not all platforms support this, so if the platform does not support asynchronous execution,
              -089     * your handler will be executed on the main thread.
              -090     * <p>
              -091     * Use this anytime your handler does not need to access state that is not considered thread safe.
              -092     * <p>
              -093     * Use context.isAsync() to determine if you are async or not.
              -094     *
              -095     * @param id
              -096     * @param handler
              -097     * @return
              -098     */
              -099    public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<C> handler) {
              -100        return this.completionMap.put(prepareCompletionId(id), handler);
              -101    }
              -102
              -103    /**
              -104     * Register a static list of command completions that will never change.
              -105     * Like @CommandCompletion, values are | (PIPE) separated.
              -106     * <p>
              -107     * Example: foo|bar|baz
              -108     *
              -109     * @param id
              -110     * @param list
              -111     * @return
              -112     */
              -113    public CommandCompletionHandler registerStaticCompletion(String id, String list) {
              -114        return registerStaticCompletion(id, ACFPatterns.PIPE.split(list));
              -115    }
              -116
              -117    /**
              -118     * Register a static list of command completions that will never change
              -119     *
              -120     * @param id
              -121     * @param completions
              -122     * @return
              -123     */
              -124    public CommandCompletionHandler registerStaticCompletion(String id, String[] completions) {
              -125        return registerStaticCompletion(id, Arrays.asList(completions));
              -126    }
              -127
              -128    /**
              -129     * Register a static list of command completions that will never change. The list is obtained from the supplier
              -130     * immediately as part of this method call.
              -131     *
              -132     * @param id
              -133     * @param supplier
              -134     * @return
              -135     */
              -136    public CommandCompletionHandler registerStaticCompletion(String id, Supplier<Collection<String>> supplier) {
              -137        return registerStaticCompletion(id, supplier.get());
              -138    }
              -139
              -140    /**
              -141     * Register a static list of command completions that will never change
              -142     *
              -143     * @param id
              -144     * @param completions
              -145     * @return
              -146     */
              -147    public CommandCompletionHandler registerStaticCompletion(String id, Collection<String> completions) {
              -148        return registerAsyncCompletion(id, x -> completions);
              -149    }
              -150
              -151    /**
              -152     * Registers a completion handler such as @players to default apply to all command parameters of the specified types
              -153     * <p>
              -154     * This enables automatic completion support for parameters without manually defining it for custom objects
              -155     *
              -156     * @param id
              -157     * @param classes
              -158     */
              -159    public void setDefaultCompletion(String id, Class... classes) {
              -160        // get completion with specified id
              -161        id = prepareCompletionId(id);
              -162        CommandCompletionHandler completion = completionMap.get(id);
              -163
              -164        if (completion == null) {
              -165            // Throw something because no completion with specified id
              -166            throw new IllegalStateException("Completion not registered for " + id);
              -167        }
              -168
              -169        for (Class clazz : classes) {
              -170            defaultCompletions.put(clazz, id);
              -171        }
              -172    }
              -173
              -174    @NotNull
              -175    private static String prepareCompletionId(String id) {
              -176        return (id.startsWith("@") ? "" : "@") + id.toLowerCase();
              -177    }
              -178
              -179    @NotNull
              -180    List<String> of(RegisteredCommand cmd, CommandIssuer sender, String[] args, boolean isAsync) {
              -181        String[] completions = ACFPatterns.SPACE.split(cmd.complete);
              -182        final int argIndex = args.length - 1;
              -183
              -184        String input = args[argIndex];
              -185
              -186        String completion = argIndex < completions.length ? completions[argIndex] : null;
              -187        if (completion == null || "*".equals(completion)) {
              -188            completion = findDefaultCompletion(cmd, args);
              -189        }
              -190
              -191        if (completion == null && completions.length > 0) {
              -192            String last = completions[completions.length - 1];
              -193            if (last.startsWith("repeat@")) {
              -194                completion = last;
              -195            } else if (argIndex >= completions.length && cmd.parameters[cmd.parameters.length - 1].consumesRest) {
              -196                completion = last;
              -197            }
              -198        }
              -199
              -200        if (completion == null) {
              -201            return Collections.singletonList(input);
              -202        }
              -203
              -204        return getCompletionValues(cmd, sender, completion, args, isAsync);
              -205    }
              -206
              -207    String findDefaultCompletion(RegisteredCommand cmd, String[] args) {
              -208        int i = 0;
              -209        for (CommandParameter param : cmd.parameters) {
              -210            if (param.canConsumeInput() && ++i == args.length) {
              -211                Class type = param.getType();
              -212                while (type != null) {
              -213                    String completion = this.defaultCompletions.get(type);
              -214                    if (completion != null) {
              -215                        return completion;
              -216                    }
              -217                    type = type.getSuperclass();
              -218                }
              -219                if (param.getType().isEnum()) {
              -220                    CommandOperationContext ctx = CommandManager.getCurrentCommandOperationContext();
              -221                    //noinspection unchecked
              -222                    ctx.enumCompletionValues = ACFUtil.enumNames((Class<? extends Enum<?>>) param.getType());
              -223                    return DEFAULT_ENUM_ID;
              -224                }
              -225                break;
              -226            }
              -227        }
              -228        return null;
              -229    }
              -230
              -231    List<String> getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) {
              -232        if (DEFAULT_ENUM_ID.equals(completion)) {
              -233            CommandOperationContext<?> ctx = CommandManager.getCurrentCommandOperationContext();
              -234            return ctx.enumCompletionValues;
              -235        }
              -236        boolean repeat = completion.startsWith("repeat@");
              -237        if (repeat) {
              -238            completion = completion.substring(6);
              -239        }
              -240        completion = manager.getCommandReplacements().replace(completion);
              -241
              -242        List<String> allCompletions = new ArrayList<>();
              -243        String input = args.length > 0 ? args[args.length - 1] : "";
              -244
              -245        for (String value : ACFPatterns.PIPE.split(completion)) {
              -246            String[] complete = ACFPatterns.COLONEQUALS.split(value, 2);
              -247            CommandCompletionHandler handler = this.completionMap.get(complete[0].toLowerCase());
              -248            if (handler != null) {
              -249                if (isAsync && !(handler instanceof AsyncCommandCompletionHandler)) {
              -250                    ACFUtil.sneaky(new SyncCompletionRequired());
              -251                    return null;
              -252                }
              -253                String config = complete.length == 1 ? null : complete[1];
              -254                CommandCompletionContext context = manager.createCompletionContext(command, sender, input, config, args);
              -255
              -256                try {
              -257                    //noinspection unchecked
              -258                    Collection<String> completions = handler.getCompletions(context);
              -259
              -260                    //Handle completions with more than one word:
              -261                    if (!repeat && completions != null
              -262                            && command.parameters[command.parameters.length - 1].consumesRest
              -263                            && args.length > ACFPatterns.SPACE.split(command.complete).length) {
              -264                        String start = String.join(" ", args);
              -265                        completions = completions.stream()
              -266                                .map(s -> {
              -267                                    if (s != null && s.split(" ").length >= args.length && ApacheCommonsLangUtil.startsWithIgnoreCase(s, start)) {
              -268                                        String[] completionArgs = s.split(" ");
              -269                                        return String.join(" ", Arrays.copyOfRange(completionArgs, args.length - 1, completionArgs.length));
              -270                                    } else {
              -271                                        return s;
              -272                                    }
              -273                                }).collect(Collectors.toList());
              -274                    }
              -275
              -276                    if (completions != null) {
              -277                        allCompletions.addAll(completions);
              -278                        continue;
              -279                    }
              -280                    //noinspection ConstantIfStatement,ConstantConditions
              -281                    if (false) { // Hack to fool compiler. since its sneakily thrown.
              -282                        throw new CommandCompletionTextLookupException();
              -283                    }
              -284                } catch (CommandCompletionTextLookupException ignored) {
              -285                    // This should only happen if some other feedback error occured.
              -286                } catch (Exception e) {
              -287                    command.handleException(sender, Arrays.asList(args), e);
              -288                }
              -289                // Something went wrong in lookup, fall back to input
              -290                return Collections.singletonList(input);
              -291            } else {
              -292                // Plaintext value
              -293                allCompletions.add(value);
              -294            }
              -295        }
              -296        return allCompletions;
              -297    }
              -298
              -299    public interface CommandCompletionHandler<C extends CommandCompletionContext> {
              -300        Collection<String> getCompletions(C context) throws InvalidCommandArgument;
              -301    }
              -302
              -303    public interface AsyncCommandCompletionHandler<C extends CommandCompletionContext> extends CommandCompletionHandler<C> {
              -304    }
              -305
              -306    public static class SyncCompletionRequired extends RuntimeException {
              -307    }
              -308
              -309}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              +027import org.jetbrains.annotations.NotNull;
              +028
              +029import java.util.ArrayList;
              +030import java.util.Arrays;
              +031import java.util.Collection;
              +032import java.util.Collections;
              +033import java.util.HashMap;
              +034import java.util.List;
              +035import java.util.Locale;
              +036import java.util.Map;
              +037import java.util.function.Supplier;
              +038import java.util.stream.Collectors;
              +039import java.util.stream.IntStream;
              +040
              +041
              +042@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
              +043public class CommandCompletions<C extends CommandCompletionContext> {
              +044    private static final String DEFAULT_ENUM_ID = "@__defaultenum__";
              +045    private final CommandManager manager;
              +046    // TODO: use a CompletionProvider that can return a delegated Id or provide values such as enum support
              +047    private Map<String, CommandCompletionHandler> completionMap = new HashMap<>();
              +048    private Map<Class, String> defaultCompletions = new HashMap<>();
              +049
              +050    public CommandCompletions(CommandManager manager) {
              +051        this.manager = manager;
              +052        registerStaticCompletion("empty", Collections.emptyList());
              +053        registerStaticCompletion("nothing", Collections.emptyList());
              +054        registerStaticCompletion("timeunits", Arrays.asList("minutes", "hours", "days", "weeks", "months", "years"));
              +055        registerAsyncCompletion("range", (c) -> {
              +056            String config = c.getConfig();
              +057            if (config == null) {
              +058                return Collections.emptyList();
              +059            }
              +060            final String[] ranges = ACFPatterns.DASH.split(config);
              +061            int start;
              +062            int end;
              +063            if (ranges.length != 2) {
              +064                start = 0;
              +065                end = ACFUtil.parseInt(ranges[0], 0);
              +066            } else {
              +067                start = ACFUtil.parseInt(ranges[0], 0);
              +068                end = ACFUtil.parseInt(ranges[1], 0);
              +069            }
              +070            return IntStream.rangeClosed(start, end).mapToObj(Integer::toString).collect(Collectors.toList());
              +071        });
              +072    }
              +073
              +074    /**
              +075     * Registr a completion handler to provide command completions based on the user input.
              +076     *
              +077     * @param id
              +078     * @param handler
              +079     * @return
              +080     */
              +081    public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<C> handler) {
              +082        return this.completionMap.put(prepareCompletionId(id), handler);
              +083    }
              +084
              +085    /**
              +086     * Registr a completion handler to provide command completions based on the user input.
              +087     * This handler is declared to be safe to be executed asynchronously.
              +088     * <p>
              +089     * Not all platforms support this, so if the platform does not support asynchronous execution,
              +090     * your handler will be executed on the main thread.
              +091     * <p>
              +092     * Use this anytime your handler does not need to access state that is not considered thread safe.
              +093     * <p>
              +094     * Use context.isAsync() to determine if you are async or not.
              +095     *
              +096     * @param id
              +097     * @param handler
              +098     * @return
              +099     */
              +100    public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<C> handler) {
              +101        return this.completionMap.put(prepareCompletionId(id), handler);
              +102    }
              +103
              +104    /**
              +105     * Register a static list of command completions that will never change.
              +106     * Like @CommandCompletion, values are | (PIPE) separated.
              +107     * <p>
              +108     * Example: foo|bar|baz
              +109     *
              +110     * @param id
              +111     * @param list
              +112     * @return
              +113     */
              +114    public CommandCompletionHandler registerStaticCompletion(String id, String list) {
              +115        return registerStaticCompletion(id, ACFPatterns.PIPE.split(list));
              +116    }
              +117
              +118    /**
              +119     * Register a static list of command completions that will never change
              +120     *
              +121     * @param id
              +122     * @param completions
              +123     * @return
              +124     */
              +125    public CommandCompletionHandler registerStaticCompletion(String id, String[] completions) {
              +126        return registerStaticCompletion(id, Arrays.asList(completions));
              +127    }
              +128
              +129    /**
              +130     * Register a static list of command completions that will never change. The list is obtained from the supplier
              +131     * immediately as part of this method call.
              +132     *
              +133     * @param id
              +134     * @param supplier
              +135     * @return
              +136     */
              +137    public CommandCompletionHandler registerStaticCompletion(String id, Supplier<Collection<String>> supplier) {
              +138        return registerStaticCompletion(id, supplier.get());
              +139    }
              +140
              +141    /**
              +142     * Register a static list of command completions that will never change
              +143     *
              +144     * @param id
              +145     * @param completions
              +146     * @return
              +147     */
              +148    public CommandCompletionHandler registerStaticCompletion(String id, Collection<String> completions) {
              +149        return registerAsyncCompletion(id, x -> completions);
              +150    }
              +151
              +152    /**
              +153     * Registers a completion handler such as @players to default apply to all command parameters of the specified types
              +154     * <p>
              +155     * This enables automatic completion support for parameters without manually defining it for custom objects
              +156     *
              +157     * @param id
              +158     * @param classes
              +159     */
              +160    public void setDefaultCompletion(String id, Class... classes) {
              +161        // get completion with specified id
              +162        id = prepareCompletionId(id);
              +163        CommandCompletionHandler completion = completionMap.get(id);
              +164
              +165        if (completion == null) {
              +166            // Throw something because no completion with specified id
              +167            throw new IllegalStateException("Completion not registered for " + id);
              +168        }
              +169
              +170        for (Class clazz : classes) {
              +171            defaultCompletions.put(clazz, id);
              +172        }
              +173    }
              +174
              +175    @NotNull
              +176    private static String prepareCompletionId(String id) {
              +177        return (id.startsWith("@") ? "" : "@") + id.toLowerCase(Locale.ENGLISH);
              +178    }
              +179
              +180    @NotNull
              +181    List<String> of(RegisteredCommand cmd, CommandIssuer sender, String[] args, boolean isAsync) {
              +182        String[] completions = ACFPatterns.SPACE.split(cmd.complete);
              +183        final int argIndex = args.length - 1;
              +184
              +185        String input = args[argIndex];
              +186
              +187        String completion = argIndex < completions.length ? completions[argIndex] : null;
              +188        if (completion == null || "*".equals(completion)) {
              +189            completion = findDefaultCompletion(cmd, args);
              +190        }
              +191
              +192        if (completion == null && completions.length > 0) {
              +193            String last = completions[completions.length - 1];
              +194            if (last.startsWith("repeat@")) {
              +195                completion = last;
              +196            } else if (argIndex >= completions.length && cmd.parameters[cmd.parameters.length - 1].consumesRest) {
              +197                completion = last;
              +198            }
              +199        }
              +200
              +201        if (completion == null) {
              +202            return Collections.singletonList(input);
              +203        }
              +204
              +205        return getCompletionValues(cmd, sender, completion, args, isAsync);
              +206    }
              +207
              +208    String findDefaultCompletion(RegisteredCommand cmd, String[] args) {
              +209        int i = 0;
              +210        for (CommandParameter param : cmd.parameters) {
              +211            if (param.canConsumeInput() && ++i == args.length) {
              +212                Class type = param.getType();
              +213                while (type != null) {
              +214                    String completion = this.defaultCompletions.get(type);
              +215                    if (completion != null) {
              +216                        return completion;
              +217                    }
              +218                    type = type.getSuperclass();
              +219                }
              +220                if (param.getType().isEnum()) {
              +221                    CommandOperationContext ctx = CommandManager.getCurrentCommandOperationContext();
              +222                    //noinspection unchecked
              +223                    ctx.enumCompletionValues = ACFUtil.enumNames((Class<? extends Enum<?>>) param.getType());
              +224                    return DEFAULT_ENUM_ID;
              +225                }
              +226                break;
              +227            }
              +228        }
              +229        return null;
              +230    }
              +231
              +232    List<String> getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) {
              +233        if (DEFAULT_ENUM_ID.equals(completion)) {
              +234            CommandOperationContext<?> ctx = CommandManager.getCurrentCommandOperationContext();
              +235            return ctx.enumCompletionValues;
              +236        }
              +237        boolean repeat = completion.startsWith("repeat@");
              +238        if (repeat) {
              +239            completion = completion.substring(6);
              +240        }
              +241        completion = manager.getCommandReplacements().replace(completion);
              +242
              +243        List<String> allCompletions = new ArrayList<>();
              +244        String input = args.length > 0 ? args[args.length - 1] : "";
              +245
              +246        for (String value : ACFPatterns.PIPE.split(completion)) {
              +247            String[] complete = ACFPatterns.COLONEQUALS.split(value, 2);
              +248            CommandCompletionHandler handler = this.completionMap.get(complete[0].toLowerCase(Locale.ENGLISH));
              +249            if (handler != null) {
              +250                if (isAsync && !(handler instanceof AsyncCommandCompletionHandler)) {
              +251                    ACFUtil.sneaky(new SyncCompletionRequired());
              +252                    return null;
              +253                }
              +254                String config = complete.length == 1 ? null : complete[1];
              +255                CommandCompletionContext context = manager.createCompletionContext(command, sender, input, config, args);
              +256
              +257                try {
              +258                    //noinspection unchecked
              +259                    Collection<String> completions = handler.getCompletions(context);
              +260
              +261                    //Handle completions with more than one word:
              +262                    if (!repeat && completions != null
              +263                            && command.parameters[command.parameters.length - 1].consumesRest
              +264                            && args.length > ACFPatterns.SPACE.split(command.complete).length) {
              +265                        String start = String.join(" ", args);
              +266                        completions = completions.stream()
              +267                                .map(s -> {
              +268                                    if (s != null && s.split(" ").length >= args.length && ApacheCommonsLangUtil.startsWithIgnoreCase(s, start)) {
              +269                                        String[] completionArgs = s.split(" ");
              +270                                        return String.join(" ", Arrays.copyOfRange(completionArgs, args.length - 1, completionArgs.length));
              +271                                    } else {
              +272                                        return s;
              +273                                    }
              +274                                }).collect(Collectors.toList());
              +275                    }
              +276
              +277                    if (completions != null) {
              +278                        allCompletions.addAll(completions);
              +279                        continue;
              +280                    }
              +281                    //noinspection ConstantIfStatement,ConstantConditions
              +282                    if (false) { // Hack to fool compiler. since its sneakily thrown.
              +283                        throw new CommandCompletionTextLookupException();
              +284                    }
              +285                } catch (CommandCompletionTextLookupException ignored) {
              +286                    // This should only happen if some other feedback error occured.
              +287                } catch (Exception e) {
              +288                    command.handleException(sender, Arrays.asList(args), e);
              +289                }
              +290                // Something went wrong in lookup, fall back to input
              +291                return Collections.singletonList(input);
              +292            } else {
              +293                // Plaintext value
              +294                allCompletions.add(value);
              +295            }
              +296        }
              +297        return allCompletions;
              +298    }
              +299
              +300    public interface CommandCompletionHandler<C extends CommandCompletionContext> {
              +301        Collection<String> getCompletions(C context) throws InvalidCommandArgument;
              +302    }
              +303
              +304    public interface AsyncCommandCompletionHandler<C extends CommandCompletionContext> extends CommandCompletionHandler<C> {
              +305    }
              +306
              +307    public static class SyncCompletionRequired extends RuntimeException {
              +308    }
              +309
              +310}
               
               
               
              @@ -377,5 +379,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.SyncCompletionRequired.html b/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.SyncCompletionRequired.html index f2dc2c4c..69176277 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.SyncCompletionRequired.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.SyncCompletionRequired.html @@ -1,320 +1,322 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              -027import org.jetbrains.annotations.NotNull;
              -028
              -029import java.util.ArrayList;
              -030import java.util.Arrays;
              -031import java.util.Collection;
              -032import java.util.Collections;
              -033import java.util.HashMap;
              -034import java.util.List;
              -035import java.util.Map;
              -036import java.util.function.Supplier;
              -037import java.util.stream.Collectors;
              -038import java.util.stream.IntStream;
              -039
              -040
              -041@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
              -042public class CommandCompletions<C extends CommandCompletionContext> {
              -043    private static final String DEFAULT_ENUM_ID = "@__defaultenum__";
              -044    private final CommandManager manager;
              -045    // TODO: use a CompletionProvider that can return a delegated Id or provide values such as enum support
              -046    private Map<String, CommandCompletionHandler> completionMap = new HashMap<>();
              -047    private Map<Class, String> defaultCompletions = new HashMap<>();
              -048
              -049    public CommandCompletions(CommandManager manager) {
              -050        this.manager = manager;
              -051        registerStaticCompletion("empty", Collections.emptyList());
              -052        registerStaticCompletion("nothing", Collections.emptyList());
              -053        registerStaticCompletion("timeunits", Arrays.asList("minutes", "hours", "days", "weeks", "months", "years"));
              -054        registerAsyncCompletion("range", (c) -> {
              -055            String config = c.getConfig();
              -056            if (config == null) {
              -057                return Collections.emptyList();
              -058            }
              -059            final String[] ranges = ACFPatterns.DASH.split(config);
              -060            int start;
              -061            int end;
              -062            if (ranges.length != 2) {
              -063                start = 0;
              -064                end = ACFUtil.parseInt(ranges[0], 0);
              -065            } else {
              -066                start = ACFUtil.parseInt(ranges[0], 0);
              -067                end = ACFUtil.parseInt(ranges[1], 0);
              -068            }
              -069            return IntStream.rangeClosed(start, end).mapToObj(Integer::toString).collect(Collectors.toList());
              -070        });
              -071    }
              -072
              -073    /**
              -074     * Registr a completion handler to provide command completions based on the user input.
              -075     *
              -076     * @param id
              -077     * @param handler
              -078     * @return
              -079     */
              -080    public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<C> handler) {
              -081        return this.completionMap.put(prepareCompletionId(id), handler);
              -082    }
              -083
              -084    /**
              -085     * Registr a completion handler to provide command completions based on the user input.
              -086     * This handler is declared to be safe to be executed asynchronously.
              -087     * <p>
              -088     * Not all platforms support this, so if the platform does not support asynchronous execution,
              -089     * your handler will be executed on the main thread.
              -090     * <p>
              -091     * Use this anytime your handler does not need to access state that is not considered thread safe.
              -092     * <p>
              -093     * Use context.isAsync() to determine if you are async or not.
              -094     *
              -095     * @param id
              -096     * @param handler
              -097     * @return
              -098     */
              -099    public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<C> handler) {
              -100        return this.completionMap.put(prepareCompletionId(id), handler);
              -101    }
              -102
              -103    /**
              -104     * Register a static list of command completions that will never change.
              -105     * Like @CommandCompletion, values are | (PIPE) separated.
              -106     * <p>
              -107     * Example: foo|bar|baz
              -108     *
              -109     * @param id
              -110     * @param list
              -111     * @return
              -112     */
              -113    public CommandCompletionHandler registerStaticCompletion(String id, String list) {
              -114        return registerStaticCompletion(id, ACFPatterns.PIPE.split(list));
              -115    }
              -116
              -117    /**
              -118     * Register a static list of command completions that will never change
              -119     *
              -120     * @param id
              -121     * @param completions
              -122     * @return
              -123     */
              -124    public CommandCompletionHandler registerStaticCompletion(String id, String[] completions) {
              -125        return registerStaticCompletion(id, Arrays.asList(completions));
              -126    }
              -127
              -128    /**
              -129     * Register a static list of command completions that will never change. The list is obtained from the supplier
              -130     * immediately as part of this method call.
              -131     *
              -132     * @param id
              -133     * @param supplier
              -134     * @return
              -135     */
              -136    public CommandCompletionHandler registerStaticCompletion(String id, Supplier<Collection<String>> supplier) {
              -137        return registerStaticCompletion(id, supplier.get());
              -138    }
              -139
              -140    /**
              -141     * Register a static list of command completions that will never change
              -142     *
              -143     * @param id
              -144     * @param completions
              -145     * @return
              -146     */
              -147    public CommandCompletionHandler registerStaticCompletion(String id, Collection<String> completions) {
              -148        return registerAsyncCompletion(id, x -> completions);
              -149    }
              -150
              -151    /**
              -152     * Registers a completion handler such as @players to default apply to all command parameters of the specified types
              -153     * <p>
              -154     * This enables automatic completion support for parameters without manually defining it for custom objects
              -155     *
              -156     * @param id
              -157     * @param classes
              -158     */
              -159    public void setDefaultCompletion(String id, Class... classes) {
              -160        // get completion with specified id
              -161        id = prepareCompletionId(id);
              -162        CommandCompletionHandler completion = completionMap.get(id);
              -163
              -164        if (completion == null) {
              -165            // Throw something because no completion with specified id
              -166            throw new IllegalStateException("Completion not registered for " + id);
              -167        }
              -168
              -169        for (Class clazz : classes) {
              -170            defaultCompletions.put(clazz, id);
              -171        }
              -172    }
              -173
              -174    @NotNull
              -175    private static String prepareCompletionId(String id) {
              -176        return (id.startsWith("@") ? "" : "@") + id.toLowerCase();
              -177    }
              -178
              -179    @NotNull
              -180    List<String> of(RegisteredCommand cmd, CommandIssuer sender, String[] args, boolean isAsync) {
              -181        String[] completions = ACFPatterns.SPACE.split(cmd.complete);
              -182        final int argIndex = args.length - 1;
              -183
              -184        String input = args[argIndex];
              -185
              -186        String completion = argIndex < completions.length ? completions[argIndex] : null;
              -187        if (completion == null || "*".equals(completion)) {
              -188            completion = findDefaultCompletion(cmd, args);
              -189        }
              -190
              -191        if (completion == null && completions.length > 0) {
              -192            String last = completions[completions.length - 1];
              -193            if (last.startsWith("repeat@")) {
              -194                completion = last;
              -195            } else if (argIndex >= completions.length && cmd.parameters[cmd.parameters.length - 1].consumesRest) {
              -196                completion = last;
              -197            }
              -198        }
              -199
              -200        if (completion == null) {
              -201            return Collections.singletonList(input);
              -202        }
              -203
              -204        return getCompletionValues(cmd, sender, completion, args, isAsync);
              -205    }
              -206
              -207    String findDefaultCompletion(RegisteredCommand cmd, String[] args) {
              -208        int i = 0;
              -209        for (CommandParameter param : cmd.parameters) {
              -210            if (param.canConsumeInput() && ++i == args.length) {
              -211                Class type = param.getType();
              -212                while (type != null) {
              -213                    String completion = this.defaultCompletions.get(type);
              -214                    if (completion != null) {
              -215                        return completion;
              -216                    }
              -217                    type = type.getSuperclass();
              -218                }
              -219                if (param.getType().isEnum()) {
              -220                    CommandOperationContext ctx = CommandManager.getCurrentCommandOperationContext();
              -221                    //noinspection unchecked
              -222                    ctx.enumCompletionValues = ACFUtil.enumNames((Class<? extends Enum<?>>) param.getType());
              -223                    return DEFAULT_ENUM_ID;
              -224                }
              -225                break;
              -226            }
              -227        }
              -228        return null;
              -229    }
              -230
              -231    List<String> getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) {
              -232        if (DEFAULT_ENUM_ID.equals(completion)) {
              -233            CommandOperationContext<?> ctx = CommandManager.getCurrentCommandOperationContext();
              -234            return ctx.enumCompletionValues;
              -235        }
              -236        boolean repeat = completion.startsWith("repeat@");
              -237        if (repeat) {
              -238            completion = completion.substring(6);
              -239        }
              -240        completion = manager.getCommandReplacements().replace(completion);
              -241
              -242        List<String> allCompletions = new ArrayList<>();
              -243        String input = args.length > 0 ? args[args.length - 1] : "";
              -244
              -245        for (String value : ACFPatterns.PIPE.split(completion)) {
              -246            String[] complete = ACFPatterns.COLONEQUALS.split(value, 2);
              -247            CommandCompletionHandler handler = this.completionMap.get(complete[0].toLowerCase());
              -248            if (handler != null) {
              -249                if (isAsync && !(handler instanceof AsyncCommandCompletionHandler)) {
              -250                    ACFUtil.sneaky(new SyncCompletionRequired());
              -251                    return null;
              -252                }
              -253                String config = complete.length == 1 ? null : complete[1];
              -254                CommandCompletionContext context = manager.createCompletionContext(command, sender, input, config, args);
              -255
              -256                try {
              -257                    //noinspection unchecked
              -258                    Collection<String> completions = handler.getCompletions(context);
              -259
              -260                    //Handle completions with more than one word:
              -261                    if (!repeat && completions != null
              -262                            && command.parameters[command.parameters.length - 1].consumesRest
              -263                            && args.length > ACFPatterns.SPACE.split(command.complete).length) {
              -264                        String start = String.join(" ", args);
              -265                        completions = completions.stream()
              -266                                .map(s -> {
              -267                                    if (s != null && s.split(" ").length >= args.length && ApacheCommonsLangUtil.startsWithIgnoreCase(s, start)) {
              -268                                        String[] completionArgs = s.split(" ");
              -269                                        return String.join(" ", Arrays.copyOfRange(completionArgs, args.length - 1, completionArgs.length));
              -270                                    } else {
              -271                                        return s;
              -272                                    }
              -273                                }).collect(Collectors.toList());
              -274                    }
              -275
              -276                    if (completions != null) {
              -277                        allCompletions.addAll(completions);
              -278                        continue;
              -279                    }
              -280                    //noinspection ConstantIfStatement,ConstantConditions
              -281                    if (false) { // Hack to fool compiler. since its sneakily thrown.
              -282                        throw new CommandCompletionTextLookupException();
              -283                    }
              -284                } catch (CommandCompletionTextLookupException ignored) {
              -285                    // This should only happen if some other feedback error occured.
              -286                } catch (Exception e) {
              -287                    command.handleException(sender, Arrays.asList(args), e);
              -288                }
              -289                // Something went wrong in lookup, fall back to input
              -290                return Collections.singletonList(input);
              -291            } else {
              -292                // Plaintext value
              -293                allCompletions.add(value);
              -294            }
              -295        }
              -296        return allCompletions;
              -297    }
              -298
              -299    public interface CommandCompletionHandler<C extends CommandCompletionContext> {
              -300        Collection<String> getCompletions(C context) throws InvalidCommandArgument;
              -301    }
              -302
              -303    public interface AsyncCommandCompletionHandler<C extends CommandCompletionContext> extends CommandCompletionHandler<C> {
              -304    }
              -305
              -306    public static class SyncCompletionRequired extends RuntimeException {
              -307    }
              -308
              -309}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              +027import org.jetbrains.annotations.NotNull;
              +028
              +029import java.util.ArrayList;
              +030import java.util.Arrays;
              +031import java.util.Collection;
              +032import java.util.Collections;
              +033import java.util.HashMap;
              +034import java.util.List;
              +035import java.util.Locale;
              +036import java.util.Map;
              +037import java.util.function.Supplier;
              +038import java.util.stream.Collectors;
              +039import java.util.stream.IntStream;
              +040
              +041
              +042@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
              +043public class CommandCompletions<C extends CommandCompletionContext> {
              +044    private static final String DEFAULT_ENUM_ID = "@__defaultenum__";
              +045    private final CommandManager manager;
              +046    // TODO: use a CompletionProvider that can return a delegated Id or provide values such as enum support
              +047    private Map<String, CommandCompletionHandler> completionMap = new HashMap<>();
              +048    private Map<Class, String> defaultCompletions = new HashMap<>();
              +049
              +050    public CommandCompletions(CommandManager manager) {
              +051        this.manager = manager;
              +052        registerStaticCompletion("empty", Collections.emptyList());
              +053        registerStaticCompletion("nothing", Collections.emptyList());
              +054        registerStaticCompletion("timeunits", Arrays.asList("minutes", "hours", "days", "weeks", "months", "years"));
              +055        registerAsyncCompletion("range", (c) -> {
              +056            String config = c.getConfig();
              +057            if (config == null) {
              +058                return Collections.emptyList();
              +059            }
              +060            final String[] ranges = ACFPatterns.DASH.split(config);
              +061            int start;
              +062            int end;
              +063            if (ranges.length != 2) {
              +064                start = 0;
              +065                end = ACFUtil.parseInt(ranges[0], 0);
              +066            } else {
              +067                start = ACFUtil.parseInt(ranges[0], 0);
              +068                end = ACFUtil.parseInt(ranges[1], 0);
              +069            }
              +070            return IntStream.rangeClosed(start, end).mapToObj(Integer::toString).collect(Collectors.toList());
              +071        });
              +072    }
              +073
              +074    /**
              +075     * Registr a completion handler to provide command completions based on the user input.
              +076     *
              +077     * @param id
              +078     * @param handler
              +079     * @return
              +080     */
              +081    public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<C> handler) {
              +082        return this.completionMap.put(prepareCompletionId(id), handler);
              +083    }
              +084
              +085    /**
              +086     * Registr a completion handler to provide command completions based on the user input.
              +087     * This handler is declared to be safe to be executed asynchronously.
              +088     * <p>
              +089     * Not all platforms support this, so if the platform does not support asynchronous execution,
              +090     * your handler will be executed on the main thread.
              +091     * <p>
              +092     * Use this anytime your handler does not need to access state that is not considered thread safe.
              +093     * <p>
              +094     * Use context.isAsync() to determine if you are async or not.
              +095     *
              +096     * @param id
              +097     * @param handler
              +098     * @return
              +099     */
              +100    public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<C> handler) {
              +101        return this.completionMap.put(prepareCompletionId(id), handler);
              +102    }
              +103
              +104    /**
              +105     * Register a static list of command completions that will never change.
              +106     * Like @CommandCompletion, values are | (PIPE) separated.
              +107     * <p>
              +108     * Example: foo|bar|baz
              +109     *
              +110     * @param id
              +111     * @param list
              +112     * @return
              +113     */
              +114    public CommandCompletionHandler registerStaticCompletion(String id, String list) {
              +115        return registerStaticCompletion(id, ACFPatterns.PIPE.split(list));
              +116    }
              +117
              +118    /**
              +119     * Register a static list of command completions that will never change
              +120     *
              +121     * @param id
              +122     * @param completions
              +123     * @return
              +124     */
              +125    public CommandCompletionHandler registerStaticCompletion(String id, String[] completions) {
              +126        return registerStaticCompletion(id, Arrays.asList(completions));
              +127    }
              +128
              +129    /**
              +130     * Register a static list of command completions that will never change. The list is obtained from the supplier
              +131     * immediately as part of this method call.
              +132     *
              +133     * @param id
              +134     * @param supplier
              +135     * @return
              +136     */
              +137    public CommandCompletionHandler registerStaticCompletion(String id, Supplier<Collection<String>> supplier) {
              +138        return registerStaticCompletion(id, supplier.get());
              +139    }
              +140
              +141    /**
              +142     * Register a static list of command completions that will never change
              +143     *
              +144     * @param id
              +145     * @param completions
              +146     * @return
              +147     */
              +148    public CommandCompletionHandler registerStaticCompletion(String id, Collection<String> completions) {
              +149        return registerAsyncCompletion(id, x -> completions);
              +150    }
              +151
              +152    /**
              +153     * Registers a completion handler such as @players to default apply to all command parameters of the specified types
              +154     * <p>
              +155     * This enables automatic completion support for parameters without manually defining it for custom objects
              +156     *
              +157     * @param id
              +158     * @param classes
              +159     */
              +160    public void setDefaultCompletion(String id, Class... classes) {
              +161        // get completion with specified id
              +162        id = prepareCompletionId(id);
              +163        CommandCompletionHandler completion = completionMap.get(id);
              +164
              +165        if (completion == null) {
              +166            // Throw something because no completion with specified id
              +167            throw new IllegalStateException("Completion not registered for " + id);
              +168        }
              +169
              +170        for (Class clazz : classes) {
              +171            defaultCompletions.put(clazz, id);
              +172        }
              +173    }
              +174
              +175    @NotNull
              +176    private static String prepareCompletionId(String id) {
              +177        return (id.startsWith("@") ? "" : "@") + id.toLowerCase(Locale.ENGLISH);
              +178    }
              +179
              +180    @NotNull
              +181    List<String> of(RegisteredCommand cmd, CommandIssuer sender, String[] args, boolean isAsync) {
              +182        String[] completions = ACFPatterns.SPACE.split(cmd.complete);
              +183        final int argIndex = args.length - 1;
              +184
              +185        String input = args[argIndex];
              +186
              +187        String completion = argIndex < completions.length ? completions[argIndex] : null;
              +188        if (completion == null || "*".equals(completion)) {
              +189            completion = findDefaultCompletion(cmd, args);
              +190        }
              +191
              +192        if (completion == null && completions.length > 0) {
              +193            String last = completions[completions.length - 1];
              +194            if (last.startsWith("repeat@")) {
              +195                completion = last;
              +196            } else if (argIndex >= completions.length && cmd.parameters[cmd.parameters.length - 1].consumesRest) {
              +197                completion = last;
              +198            }
              +199        }
              +200
              +201        if (completion == null) {
              +202            return Collections.singletonList(input);
              +203        }
              +204
              +205        return getCompletionValues(cmd, sender, completion, args, isAsync);
              +206    }
              +207
              +208    String findDefaultCompletion(RegisteredCommand cmd, String[] args) {
              +209        int i = 0;
              +210        for (CommandParameter param : cmd.parameters) {
              +211            if (param.canConsumeInput() && ++i == args.length) {
              +212                Class type = param.getType();
              +213                while (type != null) {
              +214                    String completion = this.defaultCompletions.get(type);
              +215                    if (completion != null) {
              +216                        return completion;
              +217                    }
              +218                    type = type.getSuperclass();
              +219                }
              +220                if (param.getType().isEnum()) {
              +221                    CommandOperationContext ctx = CommandManager.getCurrentCommandOperationContext();
              +222                    //noinspection unchecked
              +223                    ctx.enumCompletionValues = ACFUtil.enumNames((Class<? extends Enum<?>>) param.getType());
              +224                    return DEFAULT_ENUM_ID;
              +225                }
              +226                break;
              +227            }
              +228        }
              +229        return null;
              +230    }
              +231
              +232    List<String> getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) {
              +233        if (DEFAULT_ENUM_ID.equals(completion)) {
              +234            CommandOperationContext<?> ctx = CommandManager.getCurrentCommandOperationContext();
              +235            return ctx.enumCompletionValues;
              +236        }
              +237        boolean repeat = completion.startsWith("repeat@");
              +238        if (repeat) {
              +239            completion = completion.substring(6);
              +240        }
              +241        completion = manager.getCommandReplacements().replace(completion);
              +242
              +243        List<String> allCompletions = new ArrayList<>();
              +244        String input = args.length > 0 ? args[args.length - 1] : "";
              +245
              +246        for (String value : ACFPatterns.PIPE.split(completion)) {
              +247            String[] complete = ACFPatterns.COLONEQUALS.split(value, 2);
              +248            CommandCompletionHandler handler = this.completionMap.get(complete[0].toLowerCase(Locale.ENGLISH));
              +249            if (handler != null) {
              +250                if (isAsync && !(handler instanceof AsyncCommandCompletionHandler)) {
              +251                    ACFUtil.sneaky(new SyncCompletionRequired());
              +252                    return null;
              +253                }
              +254                String config = complete.length == 1 ? null : complete[1];
              +255                CommandCompletionContext context = manager.createCompletionContext(command, sender, input, config, args);
              +256
              +257                try {
              +258                    //noinspection unchecked
              +259                    Collection<String> completions = handler.getCompletions(context);
              +260
              +261                    //Handle completions with more than one word:
              +262                    if (!repeat && completions != null
              +263                            && command.parameters[command.parameters.length - 1].consumesRest
              +264                            && args.length > ACFPatterns.SPACE.split(command.complete).length) {
              +265                        String start = String.join(" ", args);
              +266                        completions = completions.stream()
              +267                                .map(s -> {
              +268                                    if (s != null && s.split(" ").length >= args.length && ApacheCommonsLangUtil.startsWithIgnoreCase(s, start)) {
              +269                                        String[] completionArgs = s.split(" ");
              +270                                        return String.join(" ", Arrays.copyOfRange(completionArgs, args.length - 1, completionArgs.length));
              +271                                    } else {
              +272                                        return s;
              +273                                    }
              +274                                }).collect(Collectors.toList());
              +275                    }
              +276
              +277                    if (completions != null) {
              +278                        allCompletions.addAll(completions);
              +279                        continue;
              +280                    }
              +281                    //noinspection ConstantIfStatement,ConstantConditions
              +282                    if (false) { // Hack to fool compiler. since its sneakily thrown.
              +283                        throw new CommandCompletionTextLookupException();
              +284                    }
              +285                } catch (CommandCompletionTextLookupException ignored) {
              +286                    // This should only happen if some other feedback error occured.
              +287                } catch (Exception e) {
              +288                    command.handleException(sender, Arrays.asList(args), e);
              +289                }
              +290                // Something went wrong in lookup, fall back to input
              +291                return Collections.singletonList(input);
              +292            } else {
              +293                // Plaintext value
              +294                allCompletions.add(value);
              +295            }
              +296        }
              +297        return allCompletions;
              +298    }
              +299
              +300    public interface CommandCompletionHandler<C extends CommandCompletionContext> {
              +301        Collection<String> getCompletions(C context) throws InvalidCommandArgument;
              +302    }
              +303
              +304    public interface AsyncCommandCompletionHandler<C extends CommandCompletionContext> extends CommandCompletionHandler<C> {
              +305    }
              +306
              +307    public static class SyncCompletionRequired extends RuntimeException {
              +308    }
              +309
              +310}
               
               
               
              @@ -377,5 +379,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.html b/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.html index f2dc2c4c..69176277 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandCompletions.html @@ -1,320 +1,322 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              -027import org.jetbrains.annotations.NotNull;
              -028
              -029import java.util.ArrayList;
              -030import java.util.Arrays;
              -031import java.util.Collection;
              -032import java.util.Collections;
              -033import java.util.HashMap;
              -034import java.util.List;
              -035import java.util.Map;
              -036import java.util.function.Supplier;
              -037import java.util.stream.Collectors;
              -038import java.util.stream.IntStream;
              -039
              -040
              -041@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
              -042public class CommandCompletions<C extends CommandCompletionContext> {
              -043    private static final String DEFAULT_ENUM_ID = "@__defaultenum__";
              -044    private final CommandManager manager;
              -045    // TODO: use a CompletionProvider that can return a delegated Id or provide values such as enum support
              -046    private Map<String, CommandCompletionHandler> completionMap = new HashMap<>();
              -047    private Map<Class, String> defaultCompletions = new HashMap<>();
              -048
              -049    public CommandCompletions(CommandManager manager) {
              -050        this.manager = manager;
              -051        registerStaticCompletion("empty", Collections.emptyList());
              -052        registerStaticCompletion("nothing", Collections.emptyList());
              -053        registerStaticCompletion("timeunits", Arrays.asList("minutes", "hours", "days", "weeks", "months", "years"));
              -054        registerAsyncCompletion("range", (c) -> {
              -055            String config = c.getConfig();
              -056            if (config == null) {
              -057                return Collections.emptyList();
              -058            }
              -059            final String[] ranges = ACFPatterns.DASH.split(config);
              -060            int start;
              -061            int end;
              -062            if (ranges.length != 2) {
              -063                start = 0;
              -064                end = ACFUtil.parseInt(ranges[0], 0);
              -065            } else {
              -066                start = ACFUtil.parseInt(ranges[0], 0);
              -067                end = ACFUtil.parseInt(ranges[1], 0);
              -068            }
              -069            return IntStream.rangeClosed(start, end).mapToObj(Integer::toString).collect(Collectors.toList());
              -070        });
              -071    }
              -072
              -073    /**
              -074     * Registr a completion handler to provide command completions based on the user input.
              -075     *
              -076     * @param id
              -077     * @param handler
              -078     * @return
              -079     */
              -080    public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<C> handler) {
              -081        return this.completionMap.put(prepareCompletionId(id), handler);
              -082    }
              -083
              -084    /**
              -085     * Registr a completion handler to provide command completions based on the user input.
              -086     * This handler is declared to be safe to be executed asynchronously.
              -087     * <p>
              -088     * Not all platforms support this, so if the platform does not support asynchronous execution,
              -089     * your handler will be executed on the main thread.
              -090     * <p>
              -091     * Use this anytime your handler does not need to access state that is not considered thread safe.
              -092     * <p>
              -093     * Use context.isAsync() to determine if you are async or not.
              -094     *
              -095     * @param id
              -096     * @param handler
              -097     * @return
              -098     */
              -099    public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<C> handler) {
              -100        return this.completionMap.put(prepareCompletionId(id), handler);
              -101    }
              -102
              -103    /**
              -104     * Register a static list of command completions that will never change.
              -105     * Like @CommandCompletion, values are | (PIPE) separated.
              -106     * <p>
              -107     * Example: foo|bar|baz
              -108     *
              -109     * @param id
              -110     * @param list
              -111     * @return
              -112     */
              -113    public CommandCompletionHandler registerStaticCompletion(String id, String list) {
              -114        return registerStaticCompletion(id, ACFPatterns.PIPE.split(list));
              -115    }
              -116
              -117    /**
              -118     * Register a static list of command completions that will never change
              -119     *
              -120     * @param id
              -121     * @param completions
              -122     * @return
              -123     */
              -124    public CommandCompletionHandler registerStaticCompletion(String id, String[] completions) {
              -125        return registerStaticCompletion(id, Arrays.asList(completions));
              -126    }
              -127
              -128    /**
              -129     * Register a static list of command completions that will never change. The list is obtained from the supplier
              -130     * immediately as part of this method call.
              -131     *
              -132     * @param id
              -133     * @param supplier
              -134     * @return
              -135     */
              -136    public CommandCompletionHandler registerStaticCompletion(String id, Supplier<Collection<String>> supplier) {
              -137        return registerStaticCompletion(id, supplier.get());
              -138    }
              -139
              -140    /**
              -141     * Register a static list of command completions that will never change
              -142     *
              -143     * @param id
              -144     * @param completions
              -145     * @return
              -146     */
              -147    public CommandCompletionHandler registerStaticCompletion(String id, Collection<String> completions) {
              -148        return registerAsyncCompletion(id, x -> completions);
              -149    }
              -150
              -151    /**
              -152     * Registers a completion handler such as @players to default apply to all command parameters of the specified types
              -153     * <p>
              -154     * This enables automatic completion support for parameters without manually defining it for custom objects
              -155     *
              -156     * @param id
              -157     * @param classes
              -158     */
              -159    public void setDefaultCompletion(String id, Class... classes) {
              -160        // get completion with specified id
              -161        id = prepareCompletionId(id);
              -162        CommandCompletionHandler completion = completionMap.get(id);
              -163
              -164        if (completion == null) {
              -165            // Throw something because no completion with specified id
              -166            throw new IllegalStateException("Completion not registered for " + id);
              -167        }
              -168
              -169        for (Class clazz : classes) {
              -170            defaultCompletions.put(clazz, id);
              -171        }
              -172    }
              -173
              -174    @NotNull
              -175    private static String prepareCompletionId(String id) {
              -176        return (id.startsWith("@") ? "" : "@") + id.toLowerCase();
              -177    }
              -178
              -179    @NotNull
              -180    List<String> of(RegisteredCommand cmd, CommandIssuer sender, String[] args, boolean isAsync) {
              -181        String[] completions = ACFPatterns.SPACE.split(cmd.complete);
              -182        final int argIndex = args.length - 1;
              -183
              -184        String input = args[argIndex];
              -185
              -186        String completion = argIndex < completions.length ? completions[argIndex] : null;
              -187        if (completion == null || "*".equals(completion)) {
              -188            completion = findDefaultCompletion(cmd, args);
              -189        }
              -190
              -191        if (completion == null && completions.length > 0) {
              -192            String last = completions[completions.length - 1];
              -193            if (last.startsWith("repeat@")) {
              -194                completion = last;
              -195            } else if (argIndex >= completions.length && cmd.parameters[cmd.parameters.length - 1].consumesRest) {
              -196                completion = last;
              -197            }
              -198        }
              -199
              -200        if (completion == null) {
              -201            return Collections.singletonList(input);
              -202        }
              -203
              -204        return getCompletionValues(cmd, sender, completion, args, isAsync);
              -205    }
              -206
              -207    String findDefaultCompletion(RegisteredCommand cmd, String[] args) {
              -208        int i = 0;
              -209        for (CommandParameter param : cmd.parameters) {
              -210            if (param.canConsumeInput() && ++i == args.length) {
              -211                Class type = param.getType();
              -212                while (type != null) {
              -213                    String completion = this.defaultCompletions.get(type);
              -214                    if (completion != null) {
              -215                        return completion;
              -216                    }
              -217                    type = type.getSuperclass();
              -218                }
              -219                if (param.getType().isEnum()) {
              -220                    CommandOperationContext ctx = CommandManager.getCurrentCommandOperationContext();
              -221                    //noinspection unchecked
              -222                    ctx.enumCompletionValues = ACFUtil.enumNames((Class<? extends Enum<?>>) param.getType());
              -223                    return DEFAULT_ENUM_ID;
              -224                }
              -225                break;
              -226            }
              -227        }
              -228        return null;
              -229    }
              -230
              -231    List<String> getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) {
              -232        if (DEFAULT_ENUM_ID.equals(completion)) {
              -233            CommandOperationContext<?> ctx = CommandManager.getCurrentCommandOperationContext();
              -234            return ctx.enumCompletionValues;
              -235        }
              -236        boolean repeat = completion.startsWith("repeat@");
              -237        if (repeat) {
              -238            completion = completion.substring(6);
              -239        }
              -240        completion = manager.getCommandReplacements().replace(completion);
              -241
              -242        List<String> allCompletions = new ArrayList<>();
              -243        String input = args.length > 0 ? args[args.length - 1] : "";
              -244
              -245        for (String value : ACFPatterns.PIPE.split(completion)) {
              -246            String[] complete = ACFPatterns.COLONEQUALS.split(value, 2);
              -247            CommandCompletionHandler handler = this.completionMap.get(complete[0].toLowerCase());
              -248            if (handler != null) {
              -249                if (isAsync && !(handler instanceof AsyncCommandCompletionHandler)) {
              -250                    ACFUtil.sneaky(new SyncCompletionRequired());
              -251                    return null;
              -252                }
              -253                String config = complete.length == 1 ? null : complete[1];
              -254                CommandCompletionContext context = manager.createCompletionContext(command, sender, input, config, args);
              -255
              -256                try {
              -257                    //noinspection unchecked
              -258                    Collection<String> completions = handler.getCompletions(context);
              -259
              -260                    //Handle completions with more than one word:
              -261                    if (!repeat && completions != null
              -262                            && command.parameters[command.parameters.length - 1].consumesRest
              -263                            && args.length > ACFPatterns.SPACE.split(command.complete).length) {
              -264                        String start = String.join(" ", args);
              -265                        completions = completions.stream()
              -266                                .map(s -> {
              -267                                    if (s != null && s.split(" ").length >= args.length && ApacheCommonsLangUtil.startsWithIgnoreCase(s, start)) {
              -268                                        String[] completionArgs = s.split(" ");
              -269                                        return String.join(" ", Arrays.copyOfRange(completionArgs, args.length - 1, completionArgs.length));
              -270                                    } else {
              -271                                        return s;
              -272                                    }
              -273                                }).collect(Collectors.toList());
              -274                    }
              -275
              -276                    if (completions != null) {
              -277                        allCompletions.addAll(completions);
              -278                        continue;
              -279                    }
              -280                    //noinspection ConstantIfStatement,ConstantConditions
              -281                    if (false) { // Hack to fool compiler. since its sneakily thrown.
              -282                        throw new CommandCompletionTextLookupException();
              -283                    }
              -284                } catch (CommandCompletionTextLookupException ignored) {
              -285                    // This should only happen if some other feedback error occured.
              -286                } catch (Exception e) {
              -287                    command.handleException(sender, Arrays.asList(args), e);
              -288                }
              -289                // Something went wrong in lookup, fall back to input
              -290                return Collections.singletonList(input);
              -291            } else {
              -292                // Plaintext value
              -293                allCompletions.add(value);
              -294            }
              -295        }
              -296        return allCompletions;
              -297    }
              -298
              -299    public interface CommandCompletionHandler<C extends CommandCompletionContext> {
              -300        Collection<String> getCompletions(C context) throws InvalidCommandArgument;
              -301    }
              -302
              -303    public interface AsyncCommandCompletionHandler<C extends CommandCompletionContext> extends CommandCompletionHandler<C> {
              -304    }
              -305
              -306    public static class SyncCompletionRequired extends RuntimeException {
              -307    }
              -308
              -309}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              +027import org.jetbrains.annotations.NotNull;
              +028
              +029import java.util.ArrayList;
              +030import java.util.Arrays;
              +031import java.util.Collection;
              +032import java.util.Collections;
              +033import java.util.HashMap;
              +034import java.util.List;
              +035import java.util.Locale;
              +036import java.util.Map;
              +037import java.util.function.Supplier;
              +038import java.util.stream.Collectors;
              +039import java.util.stream.IntStream;
              +040
              +041
              +042@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
              +043public class CommandCompletions<C extends CommandCompletionContext> {
              +044    private static final String DEFAULT_ENUM_ID = "@__defaultenum__";
              +045    private final CommandManager manager;
              +046    // TODO: use a CompletionProvider that can return a delegated Id or provide values such as enum support
              +047    private Map<String, CommandCompletionHandler> completionMap = new HashMap<>();
              +048    private Map<Class, String> defaultCompletions = new HashMap<>();
              +049
              +050    public CommandCompletions(CommandManager manager) {
              +051        this.manager = manager;
              +052        registerStaticCompletion("empty", Collections.emptyList());
              +053        registerStaticCompletion("nothing", Collections.emptyList());
              +054        registerStaticCompletion("timeunits", Arrays.asList("minutes", "hours", "days", "weeks", "months", "years"));
              +055        registerAsyncCompletion("range", (c) -> {
              +056            String config = c.getConfig();
              +057            if (config == null) {
              +058                return Collections.emptyList();
              +059            }
              +060            final String[] ranges = ACFPatterns.DASH.split(config);
              +061            int start;
              +062            int end;
              +063            if (ranges.length != 2) {
              +064                start = 0;
              +065                end = ACFUtil.parseInt(ranges[0], 0);
              +066            } else {
              +067                start = ACFUtil.parseInt(ranges[0], 0);
              +068                end = ACFUtil.parseInt(ranges[1], 0);
              +069            }
              +070            return IntStream.rangeClosed(start, end).mapToObj(Integer::toString).collect(Collectors.toList());
              +071        });
              +072    }
              +073
              +074    /**
              +075     * Registr a completion handler to provide command completions based on the user input.
              +076     *
              +077     * @param id
              +078     * @param handler
              +079     * @return
              +080     */
              +081    public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<C> handler) {
              +082        return this.completionMap.put(prepareCompletionId(id), handler);
              +083    }
              +084
              +085    /**
              +086     * Registr a completion handler to provide command completions based on the user input.
              +087     * This handler is declared to be safe to be executed asynchronously.
              +088     * <p>
              +089     * Not all platforms support this, so if the platform does not support asynchronous execution,
              +090     * your handler will be executed on the main thread.
              +091     * <p>
              +092     * Use this anytime your handler does not need to access state that is not considered thread safe.
              +093     * <p>
              +094     * Use context.isAsync() to determine if you are async or not.
              +095     *
              +096     * @param id
              +097     * @param handler
              +098     * @return
              +099     */
              +100    public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<C> handler) {
              +101        return this.completionMap.put(prepareCompletionId(id), handler);
              +102    }
              +103
              +104    /**
              +105     * Register a static list of command completions that will never change.
              +106     * Like @CommandCompletion, values are | (PIPE) separated.
              +107     * <p>
              +108     * Example: foo|bar|baz
              +109     *
              +110     * @param id
              +111     * @param list
              +112     * @return
              +113     */
              +114    public CommandCompletionHandler registerStaticCompletion(String id, String list) {
              +115        return registerStaticCompletion(id, ACFPatterns.PIPE.split(list));
              +116    }
              +117
              +118    /**
              +119     * Register a static list of command completions that will never change
              +120     *
              +121     * @param id
              +122     * @param completions
              +123     * @return
              +124     */
              +125    public CommandCompletionHandler registerStaticCompletion(String id, String[] completions) {
              +126        return registerStaticCompletion(id, Arrays.asList(completions));
              +127    }
              +128
              +129    /**
              +130     * Register a static list of command completions that will never change. The list is obtained from the supplier
              +131     * immediately as part of this method call.
              +132     *
              +133     * @param id
              +134     * @param supplier
              +135     * @return
              +136     */
              +137    public CommandCompletionHandler registerStaticCompletion(String id, Supplier<Collection<String>> supplier) {
              +138        return registerStaticCompletion(id, supplier.get());
              +139    }
              +140
              +141    /**
              +142     * Register a static list of command completions that will never change
              +143     *
              +144     * @param id
              +145     * @param completions
              +146     * @return
              +147     */
              +148    public CommandCompletionHandler registerStaticCompletion(String id, Collection<String> completions) {
              +149        return registerAsyncCompletion(id, x -> completions);
              +150    }
              +151
              +152    /**
              +153     * Registers a completion handler such as @players to default apply to all command parameters of the specified types
              +154     * <p>
              +155     * This enables automatic completion support for parameters without manually defining it for custom objects
              +156     *
              +157     * @param id
              +158     * @param classes
              +159     */
              +160    public void setDefaultCompletion(String id, Class... classes) {
              +161        // get completion with specified id
              +162        id = prepareCompletionId(id);
              +163        CommandCompletionHandler completion = completionMap.get(id);
              +164
              +165        if (completion == null) {
              +166            // Throw something because no completion with specified id
              +167            throw new IllegalStateException("Completion not registered for " + id);
              +168        }
              +169
              +170        for (Class clazz : classes) {
              +171            defaultCompletions.put(clazz, id);
              +172        }
              +173    }
              +174
              +175    @NotNull
              +176    private static String prepareCompletionId(String id) {
              +177        return (id.startsWith("@") ? "" : "@") + id.toLowerCase(Locale.ENGLISH);
              +178    }
              +179
              +180    @NotNull
              +181    List<String> of(RegisteredCommand cmd, CommandIssuer sender, String[] args, boolean isAsync) {
              +182        String[] completions = ACFPatterns.SPACE.split(cmd.complete);
              +183        final int argIndex = args.length - 1;
              +184
              +185        String input = args[argIndex];
              +186
              +187        String completion = argIndex < completions.length ? completions[argIndex] : null;
              +188        if (completion == null || "*".equals(completion)) {
              +189            completion = findDefaultCompletion(cmd, args);
              +190        }
              +191
              +192        if (completion == null && completions.length > 0) {
              +193            String last = completions[completions.length - 1];
              +194            if (last.startsWith("repeat@")) {
              +195                completion = last;
              +196            } else if (argIndex >= completions.length && cmd.parameters[cmd.parameters.length - 1].consumesRest) {
              +197                completion = last;
              +198            }
              +199        }
              +200
              +201        if (completion == null) {
              +202            return Collections.singletonList(input);
              +203        }
              +204
              +205        return getCompletionValues(cmd, sender, completion, args, isAsync);
              +206    }
              +207
              +208    String findDefaultCompletion(RegisteredCommand cmd, String[] args) {
              +209        int i = 0;
              +210        for (CommandParameter param : cmd.parameters) {
              +211            if (param.canConsumeInput() && ++i == args.length) {
              +212                Class type = param.getType();
              +213                while (type != null) {
              +214                    String completion = this.defaultCompletions.get(type);
              +215                    if (completion != null) {
              +216                        return completion;
              +217                    }
              +218                    type = type.getSuperclass();
              +219                }
              +220                if (param.getType().isEnum()) {
              +221                    CommandOperationContext ctx = CommandManager.getCurrentCommandOperationContext();
              +222                    //noinspection unchecked
              +223                    ctx.enumCompletionValues = ACFUtil.enumNames((Class<? extends Enum<?>>) param.getType());
              +224                    return DEFAULT_ENUM_ID;
              +225                }
              +226                break;
              +227            }
              +228        }
              +229        return null;
              +230    }
              +231
              +232    List<String> getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) {
              +233        if (DEFAULT_ENUM_ID.equals(completion)) {
              +234            CommandOperationContext<?> ctx = CommandManager.getCurrentCommandOperationContext();
              +235            return ctx.enumCompletionValues;
              +236        }
              +237        boolean repeat = completion.startsWith("repeat@");
              +238        if (repeat) {
              +239            completion = completion.substring(6);
              +240        }
              +241        completion = manager.getCommandReplacements().replace(completion);
              +242
              +243        List<String> allCompletions = new ArrayList<>();
              +244        String input = args.length > 0 ? args[args.length - 1] : "";
              +245
              +246        for (String value : ACFPatterns.PIPE.split(completion)) {
              +247            String[] complete = ACFPatterns.COLONEQUALS.split(value, 2);
              +248            CommandCompletionHandler handler = this.completionMap.get(complete[0].toLowerCase(Locale.ENGLISH));
              +249            if (handler != null) {
              +250                if (isAsync && !(handler instanceof AsyncCommandCompletionHandler)) {
              +251                    ACFUtil.sneaky(new SyncCompletionRequired());
              +252                    return null;
              +253                }
              +254                String config = complete.length == 1 ? null : complete[1];
              +255                CommandCompletionContext context = manager.createCompletionContext(command, sender, input, config, args);
              +256
              +257                try {
              +258                    //noinspection unchecked
              +259                    Collection<String> completions = handler.getCompletions(context);
              +260
              +261                    //Handle completions with more than one word:
              +262                    if (!repeat && completions != null
              +263                            && command.parameters[command.parameters.length - 1].consumesRest
              +264                            && args.length > ACFPatterns.SPACE.split(command.complete).length) {
              +265                        String start = String.join(" ", args);
              +266                        completions = completions.stream()
              +267                                .map(s -> {
              +268                                    if (s != null && s.split(" ").length >= args.length && ApacheCommonsLangUtil.startsWithIgnoreCase(s, start)) {
              +269                                        String[] completionArgs = s.split(" ");
              +270                                        return String.join(" ", Arrays.copyOfRange(completionArgs, args.length - 1, completionArgs.length));
              +271                                    } else {
              +272                                        return s;
              +273                                    }
              +274                                }).collect(Collectors.toList());
              +275                    }
              +276
              +277                    if (completions != null) {
              +278                        allCompletions.addAll(completions);
              +279                        continue;
              +280                    }
              +281                    //noinspection ConstantIfStatement,ConstantConditions
              +282                    if (false) { // Hack to fool compiler. since its sneakily thrown.
              +283                        throw new CommandCompletionTextLookupException();
              +284                    }
              +285                } catch (CommandCompletionTextLookupException ignored) {
              +286                    // This should only happen if some other feedback error occured.
              +287                } catch (Exception e) {
              +288                    command.handleException(sender, Arrays.asList(args), e);
              +289                }
              +290                // Something went wrong in lookup, fall back to input
              +291                return Collections.singletonList(input);
              +292            } else {
              +293                // Plaintext value
              +294                allCompletions.add(value);
              +295            }
              +296        }
              +297        return allCompletions;
              +298    }
              +299
              +300    public interface CommandCompletionHandler<C extends CommandCompletionContext> {
              +301        Collection<String> getCompletions(C context) throws InvalidCommandArgument;
              +302    }
              +303
              +304    public interface AsyncCommandCompletionHandler<C extends CommandCompletionContext> extends CommandCompletionHandler<C> {
              +305    }
              +306
              +307    public static class SyncCompletionRequired extends RuntimeException {
              +308    }
              +309
              +310}
               
               
               
              @@ -377,5 +379,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandConditions.Condition.html b/docs/acf-core/src-html/co/aikar/commands/CommandConditions.Condition.html index f2c73f06..8cb7fa23 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandConditions.Condition.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandConditions.Condition.html @@ -1,149 +1,151 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.util.Table;
              -027import org.jetbrains.annotations.NotNull;
              -028
              -029import java.util.HashMap;
              -030import java.util.Map;
              -031
              -032@SuppressWarnings("BooleanMethodIsAlwaysInverted") // No IDEA, you are wrong
              -033public class CommandConditions <
              -034        I extends CommandIssuer,
              -035        CEC extends CommandExecutionContext<CEC, I>,
              -036        CC extends ConditionContext<I>
              -037    > {
              -038    private CommandManager manager;
              -039    private Map<String, Condition<I>> conditions = new HashMap<>();
              -040    private Table<Class<?>, String, ParameterCondition<?, ?, ?>> paramConditions = new Table<>();
              -041
              -042    CommandConditions(CommandManager manager) {
              -043        this.manager = manager;
              -044    }
              -045
              -046    public Condition<I> addCondition(@NotNull String id, @NotNull Condition<I> handler) {
              -047        return this.conditions.put(id.toLowerCase(), handler);
              -048    }
              -049
              -050    public <P> ParameterCondition addCondition(Class<P> clazz, @NotNull String id,
              -051                                               @NotNull ParameterCondition<P, CEC, I> handler) {
              -052        return this.paramConditions.put(clazz, id.toLowerCase(), handler);
              -053    }
              -054
              -055    void validateConditions(CommandOperationContext context) throws InvalidCommandArgument {
              -056        RegisteredCommand cmd = context.getRegisteredCommand();
              -057
              -058        validateConditions(cmd.conditions, context);
              -059        validateConditions(cmd.scope, context);
              -060    }
              -061
              -062    private void validateConditions(BaseCommand scope, CommandOperationContext operationContext) throws InvalidCommandArgument {
              -063        validateConditions(scope.conditions, operationContext);
              -064
              -065        if (scope.parentCommand != null) {
              -066            validateConditions(scope.parentCommand, operationContext);
              -067        }
              -068    }
              -069
              -070    private void validateConditions(String conditions, CommandOperationContext context) throws InvalidCommandArgument {
              -071        if (conditions == null) {
              -072            return;
              -073        }
              -074
              -075        conditions = this.manager.getCommandReplacements().replace(conditions);
              -076        CommandIssuer issuer = context.getCommandIssuer();
              -077        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              -078            String[] split = ACFPatterns.COLON.split(cond, 2);
              -079            String id = split[0].toLowerCase();
              -080            Condition<I> condition = this.conditions.get(id);
              -081            if (condition == null) {
              -082                RegisteredCommand cmd = context.getRegisteredCommand();
              -083                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName());
              -084                continue;
              -085            }
              -086
              -087            String config = split.length == 2 ? split[1] : null;
              -088            //noinspection unchecked
              -089            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              -090            //noinspection unchecked
              -091            condition.validateCondition(conditionContext);
              -092        }
              -093    }
              -094
              -095    void validateConditions(CEC execContext, Object value) throws InvalidCommandArgument {
              -096        String conditions = execContext.getCommandParameter().getConditions();
              -097        if (conditions == null) {
              -098            return;
              -099        }
              -100        conditions = this.manager.getCommandReplacements().replace(conditions);
              -101        I issuer = execContext.getIssuer();
              -102        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              -103            String[] split = ACFPatterns.COLON.split(cond, 2);
              -104            ParameterCondition condition;
              -105            Class<?> cls = execContext.getParam().getType();
              -106            String id = split[0].toLowerCase();
              -107            do {
              -108                condition = this.paramConditions.get(cls, id);
              -109                if (condition == null && cls.getSuperclass() != null && cls.getSuperclass() != Object.class) {
              -110                    cls = cls.getSuperclass();
              -111                } else {
              -112                    break;
              -113                }
              -114            } while (cls != null);
              -115
              -116
              -117            if (condition == null) {
              -118                RegisteredCommand cmd = execContext.getCmd();
              -119                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName() + "::" +execContext.getParam().getName());
              -120                continue;
              -121            }
              -122            String config = split.length == 2 ? split[1] : null;
              -123            //noinspection unchecked
              -124            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              -125
              -126            //noinspection unchecked
              -127            condition.validateCondition(conditionContext, execContext, value);
              -128        }
              -129    }
              -130
              -131    public interface Condition <I extends CommandIssuer> {
              -132        void validateCondition(ConditionContext<I> context) throws InvalidCommandArgument;
              -133    }
              -134
              -135    public interface ParameterCondition <P, CEC extends CommandExecutionContext, I extends CommandIssuer> {
              -136        void validateCondition(ConditionContext<I> context, CEC execContext, P value) throws InvalidCommandArgument;
              -137    }
              -138}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.util.Table;
              +027import org.jetbrains.annotations.NotNull;
              +028
              +029import java.util.HashMap;
              +030import java.util.Locale;
              +031import java.util.Map;
              +032
              +033@SuppressWarnings("BooleanMethodIsAlwaysInverted") // No IDEA, you are wrong
              +034public class CommandConditions <
              +035        I extends CommandIssuer,
              +036        CEC extends CommandExecutionContext<CEC, I>,
              +037        CC extends ConditionContext<I>
              +038    > {
              +039    private CommandManager manager;
              +040    private Map<String, Condition<I>> conditions = new HashMap<>();
              +041    private Table<Class<?>, String, ParameterCondition<?, ?, ?>> paramConditions = new Table<>();
              +042
              +043    CommandConditions(CommandManager manager) {
              +044        this.manager = manager;
              +045    }
              +046
              +047    public Condition<I> addCondition(@NotNull String id, @NotNull Condition<I> handler) {
              +048        return this.conditions.put(id.toLowerCase(Locale.ENGLISH), handler);
              +049    }
              +050
              +051    public <P> ParameterCondition addCondition(Class<P> clazz, @NotNull String id,
              +052                                               @NotNull ParameterCondition<P, CEC, I> handler) {
              +053        return this.paramConditions.put(clazz, id.toLowerCase(Locale.ENGLISH), handler);
              +054    }
              +055
              +056    void validateConditions(CommandOperationContext context) throws InvalidCommandArgument {
              +057        RegisteredCommand cmd = context.getRegisteredCommand();
              +058
              +059        validateConditions(cmd.conditions, context);
              +060        validateConditions(cmd.scope, context);
              +061    }
              +062
              +063    private void validateConditions(BaseCommand scope, CommandOperationContext operationContext) throws InvalidCommandArgument {
              +064        validateConditions(scope.conditions, operationContext);
              +065
              +066        if (scope.parentCommand != null) {
              +067            validateConditions(scope.parentCommand, operationContext);
              +068        }
              +069    }
              +070
              +071    private void validateConditions(String conditions, CommandOperationContext context) throws InvalidCommandArgument {
              +072        if (conditions == null) {
              +073            return;
              +074        }
              +075
              +076        conditions = this.manager.getCommandReplacements().replace(conditions);
              +077        CommandIssuer issuer = context.getCommandIssuer();
              +078        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              +079            String[] split = ACFPatterns.COLON.split(cond, 2);
              +080            String id = split[0].toLowerCase(Locale.ENGLISH);
              +081            Condition<I> condition = this.conditions.get(id);
              +082            if (condition == null) {
              +083                RegisteredCommand cmd = context.getRegisteredCommand();
              +084                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName());
              +085                continue;
              +086            }
              +087
              +088            String config = split.length == 2 ? split[1] : null;
              +089            //noinspection unchecked
              +090            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              +091            //noinspection unchecked
              +092            condition.validateCondition(conditionContext);
              +093        }
              +094    }
              +095
              +096    void validateConditions(CEC execContext, Object value) throws InvalidCommandArgument {
              +097        String conditions = execContext.getCommandParameter().getConditions();
              +098        if (conditions == null) {
              +099            return;
              +100        }
              +101        conditions = this.manager.getCommandReplacements().replace(conditions);
              +102        I issuer = execContext.getIssuer();
              +103        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              +104            String[] split = ACFPatterns.COLON.split(cond, 2);
              +105            ParameterCondition condition;
              +106            Class<?> cls = execContext.getParam().getType();
              +107            String id = split[0].toLowerCase(Locale.ENGLISH);
              +108            do {
              +109                condition = this.paramConditions.get(cls, id);
              +110                if (condition == null && cls.getSuperclass() != null && cls.getSuperclass() != Object.class) {
              +111                    cls = cls.getSuperclass();
              +112                } else {
              +113                    break;
              +114                }
              +115            } while (cls != null);
              +116
              +117
              +118            if (condition == null) {
              +119                RegisteredCommand cmd = execContext.getCmd();
              +120                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName() + "::" +execContext.getParam().getName());
              +121                continue;
              +122            }
              +123            String config = split.length == 2 ? split[1] : null;
              +124            //noinspection unchecked
              +125            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              +126
              +127            //noinspection unchecked
              +128            condition.validateCondition(conditionContext, execContext, value);
              +129        }
              +130    }
              +131
              +132    public interface Condition <I extends CommandIssuer> {
              +133        void validateCondition(ConditionContext<I> context) throws InvalidCommandArgument;
              +134    }
              +135
              +136    public interface ParameterCondition <P, CEC extends CommandExecutionContext, I extends CommandIssuer> {
              +137        void validateCondition(ConditionContext<I> context, CEC execContext, P value) throws InvalidCommandArgument;
              +138    }
              +139}
               
               
               
              @@ -206,5 +208,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandConditions.ParameterCondition.html b/docs/acf-core/src-html/co/aikar/commands/CommandConditions.ParameterCondition.html index f2c73f06..8cb7fa23 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandConditions.ParameterCondition.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandConditions.ParameterCondition.html @@ -1,149 +1,151 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.util.Table;
              -027import org.jetbrains.annotations.NotNull;
              -028
              -029import java.util.HashMap;
              -030import java.util.Map;
              -031
              -032@SuppressWarnings("BooleanMethodIsAlwaysInverted") // No IDEA, you are wrong
              -033public class CommandConditions <
              -034        I extends CommandIssuer,
              -035        CEC extends CommandExecutionContext<CEC, I>,
              -036        CC extends ConditionContext<I>
              -037    > {
              -038    private CommandManager manager;
              -039    private Map<String, Condition<I>> conditions = new HashMap<>();
              -040    private Table<Class<?>, String, ParameterCondition<?, ?, ?>> paramConditions = new Table<>();
              -041
              -042    CommandConditions(CommandManager manager) {
              -043        this.manager = manager;
              -044    }
              -045
              -046    public Condition<I> addCondition(@NotNull String id, @NotNull Condition<I> handler) {
              -047        return this.conditions.put(id.toLowerCase(), handler);
              -048    }
              -049
              -050    public <P> ParameterCondition addCondition(Class<P> clazz, @NotNull String id,
              -051                                               @NotNull ParameterCondition<P, CEC, I> handler) {
              -052        return this.paramConditions.put(clazz, id.toLowerCase(), handler);
              -053    }
              -054
              -055    void validateConditions(CommandOperationContext context) throws InvalidCommandArgument {
              -056        RegisteredCommand cmd = context.getRegisteredCommand();
              -057
              -058        validateConditions(cmd.conditions, context);
              -059        validateConditions(cmd.scope, context);
              -060    }
              -061
              -062    private void validateConditions(BaseCommand scope, CommandOperationContext operationContext) throws InvalidCommandArgument {
              -063        validateConditions(scope.conditions, operationContext);
              -064
              -065        if (scope.parentCommand != null) {
              -066            validateConditions(scope.parentCommand, operationContext);
              -067        }
              -068    }
              -069
              -070    private void validateConditions(String conditions, CommandOperationContext context) throws InvalidCommandArgument {
              -071        if (conditions == null) {
              -072            return;
              -073        }
              -074
              -075        conditions = this.manager.getCommandReplacements().replace(conditions);
              -076        CommandIssuer issuer = context.getCommandIssuer();
              -077        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              -078            String[] split = ACFPatterns.COLON.split(cond, 2);
              -079            String id = split[0].toLowerCase();
              -080            Condition<I> condition = this.conditions.get(id);
              -081            if (condition == null) {
              -082                RegisteredCommand cmd = context.getRegisteredCommand();
              -083                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName());
              -084                continue;
              -085            }
              -086
              -087            String config = split.length == 2 ? split[1] : null;
              -088            //noinspection unchecked
              -089            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              -090            //noinspection unchecked
              -091            condition.validateCondition(conditionContext);
              -092        }
              -093    }
              -094
              -095    void validateConditions(CEC execContext, Object value) throws InvalidCommandArgument {
              -096        String conditions = execContext.getCommandParameter().getConditions();
              -097        if (conditions == null) {
              -098            return;
              -099        }
              -100        conditions = this.manager.getCommandReplacements().replace(conditions);
              -101        I issuer = execContext.getIssuer();
              -102        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              -103            String[] split = ACFPatterns.COLON.split(cond, 2);
              -104            ParameterCondition condition;
              -105            Class<?> cls = execContext.getParam().getType();
              -106            String id = split[0].toLowerCase();
              -107            do {
              -108                condition = this.paramConditions.get(cls, id);
              -109                if (condition == null && cls.getSuperclass() != null && cls.getSuperclass() != Object.class) {
              -110                    cls = cls.getSuperclass();
              -111                } else {
              -112                    break;
              -113                }
              -114            } while (cls != null);
              -115
              -116
              -117            if (condition == null) {
              -118                RegisteredCommand cmd = execContext.getCmd();
              -119                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName() + "::" +execContext.getParam().getName());
              -120                continue;
              -121            }
              -122            String config = split.length == 2 ? split[1] : null;
              -123            //noinspection unchecked
              -124            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              -125
              -126            //noinspection unchecked
              -127            condition.validateCondition(conditionContext, execContext, value);
              -128        }
              -129    }
              -130
              -131    public interface Condition <I extends CommandIssuer> {
              -132        void validateCondition(ConditionContext<I> context) throws InvalidCommandArgument;
              -133    }
              -134
              -135    public interface ParameterCondition <P, CEC extends CommandExecutionContext, I extends CommandIssuer> {
              -136        void validateCondition(ConditionContext<I> context, CEC execContext, P value) throws InvalidCommandArgument;
              -137    }
              -138}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.util.Table;
              +027import org.jetbrains.annotations.NotNull;
              +028
              +029import java.util.HashMap;
              +030import java.util.Locale;
              +031import java.util.Map;
              +032
              +033@SuppressWarnings("BooleanMethodIsAlwaysInverted") // No IDEA, you are wrong
              +034public class CommandConditions <
              +035        I extends CommandIssuer,
              +036        CEC extends CommandExecutionContext<CEC, I>,
              +037        CC extends ConditionContext<I>
              +038    > {
              +039    private CommandManager manager;
              +040    private Map<String, Condition<I>> conditions = new HashMap<>();
              +041    private Table<Class<?>, String, ParameterCondition<?, ?, ?>> paramConditions = new Table<>();
              +042
              +043    CommandConditions(CommandManager manager) {
              +044        this.manager = manager;
              +045    }
              +046
              +047    public Condition<I> addCondition(@NotNull String id, @NotNull Condition<I> handler) {
              +048        return this.conditions.put(id.toLowerCase(Locale.ENGLISH), handler);
              +049    }
              +050
              +051    public <P> ParameterCondition addCondition(Class<P> clazz, @NotNull String id,
              +052                                               @NotNull ParameterCondition<P, CEC, I> handler) {
              +053        return this.paramConditions.put(clazz, id.toLowerCase(Locale.ENGLISH), handler);
              +054    }
              +055
              +056    void validateConditions(CommandOperationContext context) throws InvalidCommandArgument {
              +057        RegisteredCommand cmd = context.getRegisteredCommand();
              +058
              +059        validateConditions(cmd.conditions, context);
              +060        validateConditions(cmd.scope, context);
              +061    }
              +062
              +063    private void validateConditions(BaseCommand scope, CommandOperationContext operationContext) throws InvalidCommandArgument {
              +064        validateConditions(scope.conditions, operationContext);
              +065
              +066        if (scope.parentCommand != null) {
              +067            validateConditions(scope.parentCommand, operationContext);
              +068        }
              +069    }
              +070
              +071    private void validateConditions(String conditions, CommandOperationContext context) throws InvalidCommandArgument {
              +072        if (conditions == null) {
              +073            return;
              +074        }
              +075
              +076        conditions = this.manager.getCommandReplacements().replace(conditions);
              +077        CommandIssuer issuer = context.getCommandIssuer();
              +078        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              +079            String[] split = ACFPatterns.COLON.split(cond, 2);
              +080            String id = split[0].toLowerCase(Locale.ENGLISH);
              +081            Condition<I> condition = this.conditions.get(id);
              +082            if (condition == null) {
              +083                RegisteredCommand cmd = context.getRegisteredCommand();
              +084                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName());
              +085                continue;
              +086            }
              +087
              +088            String config = split.length == 2 ? split[1] : null;
              +089            //noinspection unchecked
              +090            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              +091            //noinspection unchecked
              +092            condition.validateCondition(conditionContext);
              +093        }
              +094    }
              +095
              +096    void validateConditions(CEC execContext, Object value) throws InvalidCommandArgument {
              +097        String conditions = execContext.getCommandParameter().getConditions();
              +098        if (conditions == null) {
              +099            return;
              +100        }
              +101        conditions = this.manager.getCommandReplacements().replace(conditions);
              +102        I issuer = execContext.getIssuer();
              +103        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              +104            String[] split = ACFPatterns.COLON.split(cond, 2);
              +105            ParameterCondition condition;
              +106            Class<?> cls = execContext.getParam().getType();
              +107            String id = split[0].toLowerCase(Locale.ENGLISH);
              +108            do {
              +109                condition = this.paramConditions.get(cls, id);
              +110                if (condition == null && cls.getSuperclass() != null && cls.getSuperclass() != Object.class) {
              +111                    cls = cls.getSuperclass();
              +112                } else {
              +113                    break;
              +114                }
              +115            } while (cls != null);
              +116
              +117
              +118            if (condition == null) {
              +119                RegisteredCommand cmd = execContext.getCmd();
              +120                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName() + "::" +execContext.getParam().getName());
              +121                continue;
              +122            }
              +123            String config = split.length == 2 ? split[1] : null;
              +124            //noinspection unchecked
              +125            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              +126
              +127            //noinspection unchecked
              +128            condition.validateCondition(conditionContext, execContext, value);
              +129        }
              +130    }
              +131
              +132    public interface Condition <I extends CommandIssuer> {
              +133        void validateCondition(ConditionContext<I> context) throws InvalidCommandArgument;
              +134    }
              +135
              +136    public interface ParameterCondition <P, CEC extends CommandExecutionContext, I extends CommandIssuer> {
              +137        void validateCondition(ConditionContext<I> context, CEC execContext, P value) throws InvalidCommandArgument;
              +138    }
              +139}
               
               
               
              @@ -206,5 +208,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandConditions.html b/docs/acf-core/src-html/co/aikar/commands/CommandConditions.html index f2c73f06..8cb7fa23 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandConditions.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandConditions.html @@ -1,149 +1,151 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.util.Table;
              -027import org.jetbrains.annotations.NotNull;
              -028
              -029import java.util.HashMap;
              -030import java.util.Map;
              -031
              -032@SuppressWarnings("BooleanMethodIsAlwaysInverted") // No IDEA, you are wrong
              -033public class CommandConditions <
              -034        I extends CommandIssuer,
              -035        CEC extends CommandExecutionContext<CEC, I>,
              -036        CC extends ConditionContext<I>
              -037    > {
              -038    private CommandManager manager;
              -039    private Map<String, Condition<I>> conditions = new HashMap<>();
              -040    private Table<Class<?>, String, ParameterCondition<?, ?, ?>> paramConditions = new Table<>();
              -041
              -042    CommandConditions(CommandManager manager) {
              -043        this.manager = manager;
              -044    }
              -045
              -046    public Condition<I> addCondition(@NotNull String id, @NotNull Condition<I> handler) {
              -047        return this.conditions.put(id.toLowerCase(), handler);
              -048    }
              -049
              -050    public <P> ParameterCondition addCondition(Class<P> clazz, @NotNull String id,
              -051                                               @NotNull ParameterCondition<P, CEC, I> handler) {
              -052        return this.paramConditions.put(clazz, id.toLowerCase(), handler);
              -053    }
              -054
              -055    void validateConditions(CommandOperationContext context) throws InvalidCommandArgument {
              -056        RegisteredCommand cmd = context.getRegisteredCommand();
              -057
              -058        validateConditions(cmd.conditions, context);
              -059        validateConditions(cmd.scope, context);
              -060    }
              -061
              -062    private void validateConditions(BaseCommand scope, CommandOperationContext operationContext) throws InvalidCommandArgument {
              -063        validateConditions(scope.conditions, operationContext);
              -064
              -065        if (scope.parentCommand != null) {
              -066            validateConditions(scope.parentCommand, operationContext);
              -067        }
              -068    }
              -069
              -070    private void validateConditions(String conditions, CommandOperationContext context) throws InvalidCommandArgument {
              -071        if (conditions == null) {
              -072            return;
              -073        }
              -074
              -075        conditions = this.manager.getCommandReplacements().replace(conditions);
              -076        CommandIssuer issuer = context.getCommandIssuer();
              -077        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              -078            String[] split = ACFPatterns.COLON.split(cond, 2);
              -079            String id = split[0].toLowerCase();
              -080            Condition<I> condition = this.conditions.get(id);
              -081            if (condition == null) {
              -082                RegisteredCommand cmd = context.getRegisteredCommand();
              -083                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName());
              -084                continue;
              -085            }
              -086
              -087            String config = split.length == 2 ? split[1] : null;
              -088            //noinspection unchecked
              -089            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              -090            //noinspection unchecked
              -091            condition.validateCondition(conditionContext);
              -092        }
              -093    }
              -094
              -095    void validateConditions(CEC execContext, Object value) throws InvalidCommandArgument {
              -096        String conditions = execContext.getCommandParameter().getConditions();
              -097        if (conditions == null) {
              -098            return;
              -099        }
              -100        conditions = this.manager.getCommandReplacements().replace(conditions);
              -101        I issuer = execContext.getIssuer();
              -102        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              -103            String[] split = ACFPatterns.COLON.split(cond, 2);
              -104            ParameterCondition condition;
              -105            Class<?> cls = execContext.getParam().getType();
              -106            String id = split[0].toLowerCase();
              -107            do {
              -108                condition = this.paramConditions.get(cls, id);
              -109                if (condition == null && cls.getSuperclass() != null && cls.getSuperclass() != Object.class) {
              -110                    cls = cls.getSuperclass();
              -111                } else {
              -112                    break;
              -113                }
              -114            } while (cls != null);
              -115
              -116
              -117            if (condition == null) {
              -118                RegisteredCommand cmd = execContext.getCmd();
              -119                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName() + "::" +execContext.getParam().getName());
              -120                continue;
              -121            }
              -122            String config = split.length == 2 ? split[1] : null;
              -123            //noinspection unchecked
              -124            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              -125
              -126            //noinspection unchecked
              -127            condition.validateCondition(conditionContext, execContext, value);
              -128        }
              -129    }
              -130
              -131    public interface Condition <I extends CommandIssuer> {
              -132        void validateCondition(ConditionContext<I> context) throws InvalidCommandArgument;
              -133    }
              -134
              -135    public interface ParameterCondition <P, CEC extends CommandExecutionContext, I extends CommandIssuer> {
              -136        void validateCondition(ConditionContext<I> context, CEC execContext, P value) throws InvalidCommandArgument;
              -137    }
              -138}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.util.Table;
              +027import org.jetbrains.annotations.NotNull;
              +028
              +029import java.util.HashMap;
              +030import java.util.Locale;
              +031import java.util.Map;
              +032
              +033@SuppressWarnings("BooleanMethodIsAlwaysInverted") // No IDEA, you are wrong
              +034public class CommandConditions <
              +035        I extends CommandIssuer,
              +036        CEC extends CommandExecutionContext<CEC, I>,
              +037        CC extends ConditionContext<I>
              +038    > {
              +039    private CommandManager manager;
              +040    private Map<String, Condition<I>> conditions = new HashMap<>();
              +041    private Table<Class<?>, String, ParameterCondition<?, ?, ?>> paramConditions = new Table<>();
              +042
              +043    CommandConditions(CommandManager manager) {
              +044        this.manager = manager;
              +045    }
              +046
              +047    public Condition<I> addCondition(@NotNull String id, @NotNull Condition<I> handler) {
              +048        return this.conditions.put(id.toLowerCase(Locale.ENGLISH), handler);
              +049    }
              +050
              +051    public <P> ParameterCondition addCondition(Class<P> clazz, @NotNull String id,
              +052                                               @NotNull ParameterCondition<P, CEC, I> handler) {
              +053        return this.paramConditions.put(clazz, id.toLowerCase(Locale.ENGLISH), handler);
              +054    }
              +055
              +056    void validateConditions(CommandOperationContext context) throws InvalidCommandArgument {
              +057        RegisteredCommand cmd = context.getRegisteredCommand();
              +058
              +059        validateConditions(cmd.conditions, context);
              +060        validateConditions(cmd.scope, context);
              +061    }
              +062
              +063    private void validateConditions(BaseCommand scope, CommandOperationContext operationContext) throws InvalidCommandArgument {
              +064        validateConditions(scope.conditions, operationContext);
              +065
              +066        if (scope.parentCommand != null) {
              +067            validateConditions(scope.parentCommand, operationContext);
              +068        }
              +069    }
              +070
              +071    private void validateConditions(String conditions, CommandOperationContext context) throws InvalidCommandArgument {
              +072        if (conditions == null) {
              +073            return;
              +074        }
              +075
              +076        conditions = this.manager.getCommandReplacements().replace(conditions);
              +077        CommandIssuer issuer = context.getCommandIssuer();
              +078        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              +079            String[] split = ACFPatterns.COLON.split(cond, 2);
              +080            String id = split[0].toLowerCase(Locale.ENGLISH);
              +081            Condition<I> condition = this.conditions.get(id);
              +082            if (condition == null) {
              +083                RegisteredCommand cmd = context.getRegisteredCommand();
              +084                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName());
              +085                continue;
              +086            }
              +087
              +088            String config = split.length == 2 ? split[1] : null;
              +089            //noinspection unchecked
              +090            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              +091            //noinspection unchecked
              +092            condition.validateCondition(conditionContext);
              +093        }
              +094    }
              +095
              +096    void validateConditions(CEC execContext, Object value) throws InvalidCommandArgument {
              +097        String conditions = execContext.getCommandParameter().getConditions();
              +098        if (conditions == null) {
              +099            return;
              +100        }
              +101        conditions = this.manager.getCommandReplacements().replace(conditions);
              +102        I issuer = execContext.getIssuer();
              +103        for (String cond : ACFPatterns.PIPE.split(conditions)) {
              +104            String[] split = ACFPatterns.COLON.split(cond, 2);
              +105            ParameterCondition condition;
              +106            Class<?> cls = execContext.getParam().getType();
              +107            String id = split[0].toLowerCase(Locale.ENGLISH);
              +108            do {
              +109                condition = this.paramConditions.get(cls, id);
              +110                if (condition == null && cls.getSuperclass() != null && cls.getSuperclass() != Object.class) {
              +111                    cls = cls.getSuperclass();
              +112                } else {
              +113                    break;
              +114                }
              +115            } while (cls != null);
              +116
              +117
              +118            if (condition == null) {
              +119                RegisteredCommand cmd = execContext.getCmd();
              +120                this.manager.log(LogLevel.ERROR, "Could not find command condition " + id + " for " + cmd.method.getName() + "::" +execContext.getParam().getName());
              +121                continue;
              +122            }
              +123            String config = split.length == 2 ? split[1] : null;
              +124            //noinspection unchecked
              +125            CC conditionContext = (CC) this.manager.createConditionContext(issuer, config);
              +126
              +127            //noinspection unchecked
              +128            condition.validateCondition(conditionContext, execContext, value);
              +129        }
              +130    }
              +131
              +132    public interface Condition <I extends CommandIssuer> {
              +133        void validateCondition(ConditionContext<I> context) throws InvalidCommandArgument;
              +134    }
              +135
              +136    public interface ParameterCondition <P, CEC extends CommandExecutionContext, I extends CommandIssuer> {
              +137        void validateCondition(ConditionContext<I> context, CEC execContext, P value) throws InvalidCommandArgument;
              +138    }
              +139}
               
               
               
              @@ -206,5 +208,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandContexts.html b/docs/acf-core/src-html/co/aikar/commands/CommandContexts.html index 90643a8e..94270d05 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandContexts.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandContexts.html @@ -1,359 +1,360 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.annotation.Single;
              -027import co.aikar.commands.annotation.Split;
              -028import co.aikar.commands.annotation.Values;
              -029import co.aikar.commands.contexts.ContextResolver;
              -030import co.aikar.commands.contexts.IssuerAwareContextResolver;
              -031import co.aikar.commands.contexts.IssuerOnlyContextResolver;
              -032import co.aikar.commands.contexts.OptionalContextResolver;
              -033import org.jetbrains.annotations.NotNull;
              -034
              -035import java.math.BigDecimal;
              -036import java.math.BigInteger;
              -037import java.util.HashMap;
              -038import java.util.List;
              -039import java.util.Map;
              -040
              -041@SuppressWarnings("WeakerAccess")
              -042public class CommandContexts<R extends CommandExecutionContext<?, ? extends CommandIssuer>> {
              -043    protected final Map<Class<?>, ContextResolver<?, R>> contextMap = new HashMap<>();
              -044    protected final CommandManager manager;
              -045
              -046    CommandContexts(CommandManager manager) {
              -047        this.manager = manager;
              -048        registerIssuerOnlyContext(CommandIssuer.class, c -> c.getIssuer());
              -049        registerContext(Short.class, (c) -> {
              -050            String number = c.popFirstArg();
              -051            try {
              -052                return parseAndValidateNumber(number, c, Short.MIN_VALUE, Short.MAX_VALUE).shortValue();
              -053            } catch (NumberFormatException e) {
              -054                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -055            }
              -056        });
              -057        registerContext(short.class, (c) -> {
              -058            String number = c.popFirstArg();
              -059            try {
              -060                return parseAndValidateNumber(number, c, Short.MIN_VALUE, Short.MAX_VALUE).shortValue();
              -061            } catch (NumberFormatException e) {
              -062                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -063            }
              -064        });
              -065        registerContext(Integer.class, (c) -> {
              -066            String number = c.popFirstArg();
              -067            try {
              -068                return parseAndValidateNumber(number, c, Integer.MIN_VALUE, Integer.MAX_VALUE).intValue();
              -069            } catch (NumberFormatException e) {
              -070                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -071            }
              -072        });
              -073        registerContext(int.class, (c) -> {
              -074            String number = c.popFirstArg();
              -075            try {
              -076                return parseAndValidateNumber(number, c, Integer.MIN_VALUE, Integer.MAX_VALUE).intValue();
              -077            } catch (NumberFormatException e) {
              -078                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -079            }
              -080        });
              -081        registerContext(Long.class, (c) -> {
              -082            String number = c.popFirstArg();
              -083            try {
              -084                return parseAndValidateNumber(number, c, Long.MIN_VALUE, Long.MAX_VALUE).longValue();
              -085            } catch (NumberFormatException e) {
              -086                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -087            }
              -088        });
              -089        registerContext(long.class, (c) -> {
              -090            String number = c.popFirstArg();
              -091            try {
              -092                return parseAndValidateNumber(number, c, Long.MIN_VALUE, Long.MAX_VALUE).longValue();
              -093            } catch (NumberFormatException e) {
              -094                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -095            }
              -096        });
              -097        registerContext(Float.class, (c) -> {
              -098            String number = c.popFirstArg();
              -099            try {
              -100                return parseAndValidateNumber(number, c, -Float.MAX_VALUE, Float.MAX_VALUE).floatValue();
              -101            } catch (NumberFormatException e) {
              -102                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -103            }
              -104        });
              -105        registerContext(float.class, (c) -> {
              -106            String number = c.popFirstArg();
              -107            try {
              -108                return parseAndValidateNumber(number, c, -Float.MAX_VALUE, Float.MAX_VALUE).floatValue();
              -109            } catch (NumberFormatException e) {
              -110                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -111            }
              -112        });
              -113        registerContext(Double.class, (c) -> {
              -114            String number = c.popFirstArg();
              -115            try {
              -116                return parseAndValidateNumber(number, c, -Double.MAX_VALUE, Double.MAX_VALUE).doubleValue();
              -117            } catch (NumberFormatException e) {
              -118                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -119            }
              -120        });
              -121        registerContext(double.class, (c) -> {
              -122            String number = c.popFirstArg();
              -123            try {
              -124                return parseAndValidateNumber(number, c, -Double.MAX_VALUE, Double.MAX_VALUE).doubleValue();
              -125            } catch (NumberFormatException e) {
              -126                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -127            }
              -128        });
              -129        registerContext(Number.class, (c) -> {
              -130            String number = c.popFirstArg();
              -131            try {
              -132                return parseAndValidateNumber(number, c, -Double.MAX_VALUE, Double.MAX_VALUE);
              -133            } catch (NumberFormatException e) {
              -134                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              -135            }
              -136        });
              -137        registerContext(BigDecimal.class, (c) -> {
              -138            String numberStr = c.popFirstArg();
              -139            try {
              -140                BigDecimal number = ACFUtil.parseBigNumber(numberStr, c.hasFlag("suffixes"));
              -141                validateMinMax(c, number);
              -142                return number;
              -143            } catch (NumberFormatException e) {
              -144                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", numberStr);
              -145            }
              -146        });
              -147        registerContext(BigInteger.class, (c) -> {
              -148            String numberStr = c.popFirstArg();
              -149            try {
              -150                BigDecimal number = ACFUtil.parseBigNumber(numberStr, c.hasFlag("suffixes"));
              -151                validateMinMax(c, number);
              -152                return number.toBigIntegerExact();
              -153            } catch (NumberFormatException e) {
              -154                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", numberStr);
              -155            }
              -156        });
              -157        registerContext(Boolean.class, (c) -> ACFUtil.isTruthy(c.popFirstArg()));
              -158        registerContext(boolean.class, (c) -> ACFUtil.isTruthy(c.popFirstArg()));
              -159        registerContext(char.class, c -> {
              -160            String s = c.popFirstArg();
              -161            if (s.length() > 1) {
              -162                throw new InvalidCommandArgument(MessageKeys.MUST_BE_MAX_LENGTH, "{max}", String.valueOf(1));
              -163            }
              -164            return s.charAt(0);
              -165        });
              -166        registerContext(String.class, (c) -> {
              -167            // This will fail fast, its either in the values or its not
              -168            if (c.hasAnnotation(Values.class)) {
              -169                return c.popFirstArg();
              -170            }
              -171            String ret = (c.isLastArg() && !c.hasAnnotation(Single.class)) ?
              -172                    ACFUtil.join(c.getArgs())
              -173                    :
              -174                    c.popFirstArg();
              -175
              -176            Integer minLen = c.getFlagValue("minlen", (Integer) null);
              -177            Integer maxLen = c.getFlagValue("maxlen", (Integer) null);
              -178            if (minLen != null) {
              -179                if (ret.length() < minLen) {
              -180                    throw new InvalidCommandArgument(MessageKeys.MUST_BE_MIN_LENGTH, "{min}", String.valueOf(minLen));
              -181                }
              -182            }
              -183            if (maxLen != null) {
              -184                if (ret.length() > maxLen) {
              -185                    throw new InvalidCommandArgument(MessageKeys.MUST_BE_MAX_LENGTH, "{max}", String.valueOf(maxLen));
              -186                }
              -187            }
              -188
              -189            return ret;
              -190        });
              -191        registerContext(String[].class, (c) -> {
              -192            String val;
              -193            List<String> args = c.getArgs();
              -194            if (c.isLastArg() && !c.hasAnnotation(Single.class)) {
              -195                val = ACFUtil.join(args);
              -196            } else {
              -197                val = c.popFirstArg();
              -198            }
              -199            String split = c.getAnnotationValue(Split.class, Annotations.NOTHING | Annotations.NO_EMPTY);
              -200            if (split != null) {
              -201                if (val.isEmpty()) {
              -202                    throw new InvalidCommandArgument();
              -203                }
              -204                return ACFPatterns.getPattern(split).split(val);
              -205            } else if (!c.isLastArg()) {
              -206                ACFUtil.sneaky(new IllegalStateException("Weird Command signature... String[] should be last or @Split"));
              -207            }
              -208
              -209            String[] result = args.toArray(new String[0]);
              -210            args.clear();
              -211            return result;
              -212        });
              -213
              -214        registerContext(Enum.class, (c) -> {
              -215            final String first = c.popFirstArg();
              -216            //noinspection unchecked
              -217            Class<? extends Enum<?>> enumCls = (Class<? extends Enum<?>>) c.getParam().getType();
              -218            Enum<?> match = ACFUtil.simpleMatch(enumCls, first);
              -219            if (match == null) {
              -220                List<String> names = ACFUtil.enumNames(enumCls);
              -221                throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", ACFUtil.join(names, ", "));
              -222            }
              -223            return match;
              -224        });
              -225        registerOptionalContext(CommandHelp.class, (c) -> {
              -226            String first = c.getFirstArg();
              -227            String last = c.getLastArg();
              -228            int page = 1;
              -229            List<String> search = null;
              -230            if (last != null && ACFUtil.isInteger(last)) {
              -231                c.popLastArg();
              -232                page = ACFUtil.parseInt(last);
              -233                if (!c.getArgs().isEmpty()) {
              -234                    search = c.getArgs();
              -235                }
              -236            } else if (first != null && ACFUtil.isInteger(first)) {
              -237                c.popFirstArg();
              -238                page = ACFUtil.parseInt(first);
              -239                if (!c.getArgs().isEmpty()) {
              -240                    search = c.getArgs();
              -241                }
              -242            } else if (!c.getArgs().isEmpty()) {
              -243                search = c.getArgs();
              -244            }
              -245            CommandHelp commandHelp = manager.generateCommandHelp();
              -246            commandHelp.setPage(page);
              -247            Integer perPage = c.getFlagValue("perpage", (Integer) null);
              -248            if (perPage != null) {
              -249                commandHelp.setPerPage(perPage);
              -250            }
              -251
              -252            // check if we have an exact match and should display the help page for that sub command instead
              -253            if (search != null) {
              -254                String cmd = String.join(" ", search);
              -255                if (commandHelp.testExactMatch(cmd)) {
              -256                    return commandHelp;
              -257                }
              -258            }
              -259
              -260            commandHelp.setSearch(search);
              -261            return commandHelp;
              -262        });
              -263    }
              -264
              -265    @NotNull
              -266    private Number parseAndValidateNumber(String number, R c, Number minValue, Number maxValue) throws InvalidCommandArgument {
              -267        final Number val = ACFUtil.parseNumber(number, c.hasFlag("suffixes"));
              -268        validateMinMax(c, val, minValue, maxValue);
              -269        return val;
              -270    }
              -271
              -272    private void validateMinMax(R c, Number val) throws InvalidCommandArgument {
              -273        validateMinMax(c, val, null, null);
              -274    }
              -275
              -276    private void validateMinMax(R c, Number val, Number minValue, Number maxValue) throws InvalidCommandArgument {
              -277        minValue = c.getFlagValue("min", minValue);
              -278        maxValue = c.getFlagValue("max", maxValue);
              -279        if (maxValue != null && val.doubleValue() > maxValue.doubleValue()) {
              -280            throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_AT_MOST, "{max}", String.valueOf(maxValue));
              -281        }
              -282        if (minValue != null && val.doubleValue() < minValue.doubleValue()) {
              -283            throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_AT_LEAST, "{min}", String.valueOf(minValue));
              -284        }
              -285    }
              -286
              -287
              -288    /**
              -289     * @see #registerIssuerAwareContext(Class, IssuerAwareContextResolver)
              -290     * @deprecated Please switch to {@link #registerIssuerAwareContext(Class, IssuerAwareContextResolver)}
              -291     * as the core wants to use the platform agnostic term of "Issuer" instead of Sender
              -292     */
              -293    @Deprecated
              -294    public <T> void registerSenderAwareContext(Class<T> context, IssuerAwareContextResolver<T, R> supplier) {
              -295        contextMap.put(context, supplier);
              -296    }
              -297
              -298    /**
              -299     * Registers a context resolver that may conditionally consume input, falling back to using the context of the
              -300     * issuer to potentially fulfill this context.
              -301     * You may call {@link CommandExecutionContext#getFirstArg()} and then conditionally call {@link CommandExecutionContext#popFirstArg()}
              -302     * if you want to consume that input.
              -303     */
              -304    public <T> void registerIssuerAwareContext(Class<T> context, IssuerAwareContextResolver<T, R> supplier) {
              -305        contextMap.put(context, supplier);
              -306    }
              -307
              -308    /**
              -309     * Registers a context resolver that will never consume input. It will always satisfy its context based on the
              -310     * issuer of the command, so it will not appear in syntax strings.
              -311     */
              -312    public <T> void registerIssuerOnlyContext(Class<T> context, IssuerOnlyContextResolver<T, R> supplier) {
              -313        contextMap.put(context, supplier);
              -314    }
              -315
              -316    /**
              -317     * Registers a context that can safely accept a null input from the command issuer to resolve. This resolver should always
              -318     * call {@link CommandExecutionContext#popFirstArg()}
              -319     */
              -320    public <T> void registerOptionalContext(Class<T> context, OptionalContextResolver<T, R> supplier) {
              -321        contextMap.put(context, supplier);
              -322    }
              -323
              -324    /**
              -325     * Registers a context that requires input from the command issuer to resolve. This resolver should always
              -326     * call {@link CommandExecutionContext#popFirstArg()}
              -327     */
              -328    public <T> void registerContext(Class<T> context, ContextResolver<T, R> supplier) {
              -329        contextMap.put(context, supplier);
              -330    }
              -331
              -332    public ContextResolver<?, R> getResolver(Class<?> type) {
              -333        Class<?> rootType = type;
              -334        do {
              -335            if (type == Object.class) {
              -336                break;
              -337            }
              -338
              -339            final ContextResolver<?, R> resolver = contextMap.get(type);
              -340            if (resolver != null) {
              -341                return resolver;
              -342            }
              -343        } while ((type = type.getSuperclass()) != null);
              -344
              -345        this.manager.log(LogLevel.ERROR, "Could not find context resolver", new IllegalStateException("No context resolver defined for " + rootType.getName()));
              -346        return null;
              -347    }
              -348}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.annotation.Single;
              +027import co.aikar.commands.annotation.Split;
              +028import co.aikar.commands.annotation.Values;
              +029import co.aikar.commands.contexts.ContextResolver;
              +030import co.aikar.commands.contexts.IssuerAwareContextResolver;
              +031import co.aikar.commands.contexts.IssuerOnlyContextResolver;
              +032import co.aikar.commands.contexts.OptionalContextResolver;
              +033import org.jetbrains.annotations.NotNull;
              +034
              +035import java.math.BigDecimal;
              +036import java.math.BigInteger;
              +037import java.util.HashMap;
              +038import java.util.List;
              +039import java.util.Map;
              +040
              +041@SuppressWarnings("WeakerAccess")
              +042public class CommandContexts<R extends CommandExecutionContext<?, ? extends CommandIssuer>> {
              +043    protected final Map<Class<?>, ContextResolver<?, R>> contextMap = new HashMap<>();
              +044    protected final CommandManager manager;
              +045
              +046    CommandContexts(CommandManager manager) {
              +047        this.manager = manager;
              +048        registerIssuerOnlyContext(CommandIssuer.class, c -> c.getIssuer());
              +049        registerContext(Short.class, (c) -> {
              +050            String number = c.popFirstArg();
              +051            try {
              +052                return parseAndValidateNumber(number, c, Short.MIN_VALUE, Short.MAX_VALUE).shortValue();
              +053            } catch (NumberFormatException e) {
              +054                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +055            }
              +056        });
              +057        registerContext(short.class, (c) -> {
              +058            String number = c.popFirstArg();
              +059            try {
              +060                return parseAndValidateNumber(number, c, Short.MIN_VALUE, Short.MAX_VALUE).shortValue();
              +061            } catch (NumberFormatException e) {
              +062                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +063            }
              +064        });
              +065        registerContext(Integer.class, (c) -> {
              +066            String number = c.popFirstArg();
              +067            try {
              +068                return parseAndValidateNumber(number, c, Integer.MIN_VALUE, Integer.MAX_VALUE).intValue();
              +069            } catch (NumberFormatException e) {
              +070                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +071            }
              +072        });
              +073        registerContext(int.class, (c) -> {
              +074            String number = c.popFirstArg();
              +075            try {
              +076                return parseAndValidateNumber(number, c, Integer.MIN_VALUE, Integer.MAX_VALUE).intValue();
              +077            } catch (NumberFormatException e) {
              +078                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +079            }
              +080        });
              +081        registerContext(Long.class, (c) -> {
              +082            String number = c.popFirstArg();
              +083            try {
              +084                return parseAndValidateNumber(number, c, Long.MIN_VALUE, Long.MAX_VALUE).longValue();
              +085            } catch (NumberFormatException e) {
              +086                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +087            }
              +088        });
              +089        registerContext(long.class, (c) -> {
              +090            String number = c.popFirstArg();
              +091            try {
              +092                return parseAndValidateNumber(number, c, Long.MIN_VALUE, Long.MAX_VALUE).longValue();
              +093            } catch (NumberFormatException e) {
              +094                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +095            }
              +096        });
              +097        registerContext(Float.class, (c) -> {
              +098            String number = c.popFirstArg();
              +099            try {
              +100                return parseAndValidateNumber(number, c, -Float.MAX_VALUE, Float.MAX_VALUE).floatValue();
              +101            } catch (NumberFormatException e) {
              +102                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +103            }
              +104        });
              +105        registerContext(float.class, (c) -> {
              +106            String number = c.popFirstArg();
              +107            try {
              +108                return parseAndValidateNumber(number, c, -Float.MAX_VALUE, Float.MAX_VALUE).floatValue();
              +109            } catch (NumberFormatException e) {
              +110                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +111            }
              +112        });
              +113        registerContext(Double.class, (c) -> {
              +114            String number = c.popFirstArg();
              +115            try {
              +116                return parseAndValidateNumber(number, c, -Double.MAX_VALUE, Double.MAX_VALUE).doubleValue();
              +117            } catch (NumberFormatException e) {
              +118                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +119            }
              +120        });
              +121        registerContext(double.class, (c) -> {
              +122            String number = c.popFirstArg();
              +123            try {
              +124                return parseAndValidateNumber(number, c, -Double.MAX_VALUE, Double.MAX_VALUE).doubleValue();
              +125            } catch (NumberFormatException e) {
              +126                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +127            }
              +128        });
              +129        registerContext(Number.class, (c) -> {
              +130            String number = c.popFirstArg();
              +131            try {
              +132                return parseAndValidateNumber(number, c, -Double.MAX_VALUE, Double.MAX_VALUE);
              +133            } catch (NumberFormatException e) {
              +134                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", number);
              +135            }
              +136        });
              +137        registerContext(BigDecimal.class, (c) -> {
              +138            String numberStr = c.popFirstArg();
              +139            try {
              +140                BigDecimal number = ACFUtil.parseBigNumber(numberStr, c.hasFlag("suffixes"));
              +141                validateMinMax(c, number);
              +142                return number;
              +143            } catch (NumberFormatException e) {
              +144                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", numberStr);
              +145            }
              +146        });
              +147        registerContext(BigInteger.class, (c) -> {
              +148            String numberStr = c.popFirstArg();
              +149            try {
              +150                BigDecimal number = ACFUtil.parseBigNumber(numberStr, c.hasFlag("suffixes"));
              +151                validateMinMax(c, number);
              +152                return number.toBigIntegerExact();
              +153            } catch (NumberFormatException e) {
              +154                throw new InvalidCommandArgument(MessageKeys.MUST_BE_A_NUMBER, "{num}", numberStr);
              +155            }
              +156        });
              +157        registerContext(Boolean.class, (c) -> ACFUtil.isTruthy(c.popFirstArg()));
              +158        registerContext(boolean.class, (c) -> ACFUtil.isTruthy(c.popFirstArg()));
              +159        registerContext(char.class, c -> {
              +160            String s = c.popFirstArg();
              +161            if (s.length() > 1) {
              +162                throw new InvalidCommandArgument(MessageKeys.MUST_BE_MAX_LENGTH, "{max}", String.valueOf(1));
              +163            }
              +164            return s.charAt(0);
              +165        });
              +166        registerContext(String.class, (c) -> {
              +167            // This will fail fast, its either in the values or its not
              +168            if (c.hasAnnotation(Values.class)) {
              +169                return c.popFirstArg();
              +170            }
              +171            String ret = (c.isLastArg() && !c.hasAnnotation(Single.class)) ?
              +172                    ACFUtil.join(c.getArgs())
              +173                    :
              +174                    c.popFirstArg();
              +175
              +176            Integer minLen = c.getFlagValue("minlen", (Integer) null);
              +177            Integer maxLen = c.getFlagValue("maxlen", (Integer) null);
              +178            if (minLen != null) {
              +179                if (ret.length() < minLen) {
              +180                    throw new InvalidCommandArgument(MessageKeys.MUST_BE_MIN_LENGTH, "{min}", String.valueOf(minLen));
              +181                }
              +182            }
              +183            if (maxLen != null) {
              +184                if (ret.length() > maxLen) {
              +185                    throw new InvalidCommandArgument(MessageKeys.MUST_BE_MAX_LENGTH, "{max}", String.valueOf(maxLen));
              +186                }
              +187            }
              +188
              +189            return ret;
              +190        });
              +191        registerContext(String[].class, (c) -> {
              +192            String val;
              +193            List<String> args = c.getArgs();
              +194            if (c.isLastArg() && !c.hasAnnotation(Single.class)) {
              +195                val = ACFUtil.join(args);
              +196            } else {
              +197                val = c.popFirstArg();
              +198            }
              +199            String split = c.getAnnotationValue(Split.class, Annotations.NOTHING | Annotations.NO_EMPTY);
              +200            if (split != null) {
              +201                if (val.isEmpty()) {
              +202                    throw new InvalidCommandArgument();
              +203                }
              +204                return ACFPatterns.getPattern(split).split(val);
              +205            } else if (!c.isLastArg()) {
              +206                ACFUtil.sneaky(new IllegalStateException("Weird Command signature... String[] should be last or @Split"));
              +207            }
              +208
              +209            String[] result = args.toArray(new String[0]);
              +210            args.clear();
              +211            return result;
              +212        });
              +213
              +214        registerContext(Enum.class, (c) -> {
              +215            final String first = c.popFirstArg();
              +216            //noinspection unchecked
              +217            Class<? extends Enum<?>> enumCls = (Class<? extends Enum<?>>) c.getParam().getType();
              +218            Enum<?> match = ACFUtil.simpleMatch(enumCls, first);
              +219            if (match == null) {
              +220                List<String> names = ACFUtil.enumNames(enumCls);
              +221                throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", ACFUtil.join(names, ", "));
              +222            }
              +223            return match;
              +224        });
              +225        registerOptionalContext(CommandHelp.class, (c) -> {
              +226            String first = c.getFirstArg();
              +227            String last = c.getLastArg();
              +228            int page = 1;
              +229            List<String> search = null;
              +230            if (last != null && ACFUtil.isInteger(last)) {
              +231                c.popLastArg();
              +232                page = ACFUtil.parseInt(last);
              +233                if (!c.getArgs().isEmpty()) {
              +234                    search = c.getArgs();
              +235                }
              +236            } else if (first != null && ACFUtil.isInteger(first)) {
              +237                c.popFirstArg();
              +238                page = ACFUtil.parseInt(first);
              +239                if (!c.getArgs().isEmpty()) {
              +240                    search = c.getArgs();
              +241                }
              +242            } else if (!c.getArgs().isEmpty()) {
              +243                search = c.getArgs();
              +244            }
              +245            CommandHelp commandHelp = manager.generateCommandHelp();
              +246            commandHelp.setPage(page);
              +247            Integer perPage = c.getFlagValue("perpage", (Integer) null);
              +248            if (perPage != null) {
              +249                commandHelp.setPerPage(perPage);
              +250            }
              +251
              +252            // check if we have an exact match and should display the help page for that sub command instead
              +253            if (search != null) {
              +254                String cmd = String.join(" ", search);
              +255                if (commandHelp.testExactMatch(cmd)) {
              +256                    return commandHelp;
              +257                }
              +258            }
              +259
              +260            commandHelp.setSearch(search);
              +261            return commandHelp;
              +262        });
              +263    }
              +264
              +265    @NotNull
              +266    private Number parseAndValidateNumber(String number, R c, Number minValue, Number maxValue) throws InvalidCommandArgument {
              +267        final Number val = ACFUtil.parseNumber(number, c.hasFlag("suffixes"));
              +268        validateMinMax(c, val, minValue, maxValue);
              +269        return val;
              +270    }
              +271
              +272    private void validateMinMax(R c, Number val) throws InvalidCommandArgument {
              +273        validateMinMax(c, val, null, null);
              +274    }
              +275
              +276    private void validateMinMax(R c, Number val, Number minValue, Number maxValue) throws InvalidCommandArgument {
              +277        minValue = c.getFlagValue("min", minValue);
              +278        maxValue = c.getFlagValue("max", maxValue);
              +279        if (maxValue != null && val.doubleValue() > maxValue.doubleValue()) {
              +280            throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_AT_MOST, "{max}", String.valueOf(maxValue));
              +281        }
              +282        if (minValue != null && val.doubleValue() < minValue.doubleValue()) {
              +283            throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_AT_LEAST, "{min}", String.valueOf(minValue));
              +284        }
              +285    }
              +286
              +287
              +288    /**
              +289     * @see #registerIssuerAwareContext(Class, IssuerAwareContextResolver)
              +290     * @deprecated Please switch to {@link #registerIssuerAwareContext(Class, IssuerAwareContextResolver)}
              +291     * as the core wants to use the platform agnostic term of "Issuer" instead of Sender
              +292     */
              +293    @Deprecated
              +294    public <T> void registerSenderAwareContext(Class<T> context, IssuerAwareContextResolver<T, R> supplier) {
              +295        contextMap.put(context, supplier);
              +296    }
              +297
              +298    /**
              +299     * Registers a context resolver that may conditionally consume input, falling back to using the context of the
              +300     * issuer to potentially fulfill this context.
              +301     * You may call {@link CommandExecutionContext#getFirstArg()} and then conditionally call {@link CommandExecutionContext#popFirstArg()}
              +302     * if you want to consume that input.
              +303     */
              +304    public <T> void registerIssuerAwareContext(Class<T> context, IssuerAwareContextResolver<T, R> supplier) {
              +305        contextMap.put(context, supplier);
              +306    }
              +307
              +308    /**
              +309     * Registers a context resolver that will never consume input. It will always satisfy its context based on the
              +310     * issuer of the command, so it will not appear in syntax strings.
              +311     */
              +312    public <T> void registerIssuerOnlyContext(Class<T> context, IssuerOnlyContextResolver<T, R> supplier) {
              +313        contextMap.put(context, supplier);
              +314    }
              +315
              +316    /**
              +317     * Registers a context that can safely accept a null input from the command issuer to resolve. This resolver should always
              +318     * call {@link CommandExecutionContext#popFirstArg()}
              +319     */
              +320    public <T> void registerOptionalContext(Class<T> context, OptionalContextResolver<T, R> supplier) {
              +321        contextMap.put(context, supplier);
              +322    }
              +323
              +324    /**
              +325     * Registers a context that requires input from the command issuer to resolve. This resolver should always
              +326     * call {@link CommandExecutionContext#popFirstArg()}
              +327     */
              +328    public <T> void registerContext(Class<T> context, ContextResolver<T, R> supplier) {
              +329        contextMap.put(context, supplier);
              +330    }
              +331
              +332    public ContextResolver<?, R> getResolver(Class<?> type) {
              +333        Class<?> rootType = type;
              +334        do {
              +335            if (type == Object.class) {
              +336                break;
              +337            }
              +338
              +339            final ContextResolver<?, R> resolver = contextMap.get(type);
              +340            if (resolver != null) {
              +341                return resolver;
              +342            }
              +343        } while ((type = type.getSuperclass()) != null);
              +344
              +345        this.manager.log(LogLevel.ERROR, "Could not find context resolver", new IllegalStateException("No context resolver defined for " + rootType.getName()));
              +346        return null;
              +347    }
              +348}
               
               
               
              @@ -416,5 +417,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandExecutionContext.html b/docs/acf-core/src-html/co/aikar/commands/CommandExecutionContext.html index 5acbca05..2fb819f7 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandExecutionContext.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandExecutionContext.html @@ -1,249 +1,250 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import java.lang.annotation.Annotation;
              -027import java.lang.reflect.Parameter;
              -028import java.util.List;
              -029import java.util.Map;
              -030import java.util.Set;
              -031
              -032@SuppressWarnings({"WeakerAccess", "unchecked"})
              -033public class CommandExecutionContext<CEC extends CommandExecutionContext, I extends CommandIssuer> {
              -034    private final RegisteredCommand cmd;
              -035    private final CommandParameter param;
              -036    protected final I issuer;
              -037    private final List<String> args;
              -038    private final int index;
              -039    private final Map<String, Object> passedArgs;
              -040    private final Map<String, String> flags;
              -041    private final CommandManager manager;
              -042
              -043    CommandExecutionContext(RegisteredCommand cmd, CommandParameter param, I sender, List<String> args,
              -044                            int index, Map<String, Object> passedArgs) {
              -045        this.cmd = cmd;
              -046        this.manager = cmd.scope.manager;
              -047        this.param = param;
              -048        this.issuer = sender;
              -049        this.args = args;
              -050        this.index = index;
              -051        this.passedArgs = passedArgs;
              -052        this.flags = param.getFlags();
              -053
              -054    }
              -055
              -056    public String popFirstArg() {
              -057        return !args.isEmpty() ? args.remove(0) : null;
              -058    }
              -059
              -060    public String popLastArg() {
              -061        return !args.isEmpty() ? args.remove(args.size() - 1) : null;
              -062    }
              -063
              -064    public String getFirstArg() {
              -065        return !args.isEmpty() ? args.get(0) : null;
              -066    }
              -067
              -068    public String getLastArg() {
              -069        return !args.isEmpty() ? args.get(args.size() - 1) : null;
              -070    }
              -071
              -072    public boolean isLastArg() {
              -073        return cmd.parameters.length - 1 == index;
              -074    }
              -075
              -076    public int getNumParams() {
              -077        return cmd.parameters.length;
              -078    }
              -079
              -080    public boolean canOverridePlayerContext() {
              -081        return cmd.requiredResolvers >= args.size();
              -082    }
              -083
              -084    public Object getResolvedArg(String arg) {
              -085        return passedArgs.get(arg);
              -086    }
              -087
              -088    public Object getResolvedArg(Class<?>... classes) {
              -089        for (Class<?> clazz : classes) {
              -090            for (Object passedArg : passedArgs.values()) {
              -091                if (clazz.isInstance(passedArg)) {
              -092                    return passedArg;
              -093                }
              -094            }
              -095        }
              -096
              -097        return null;
              -098    }
              -099
              -100    public <T> T getResolvedArg(String key, Class<?>... classes) {
              -101        final Object o = passedArgs.get(key);
              -102        for (Class<?> clazz : classes) {
              -103            if (clazz.isInstance(o)) {
              -104                return (T) o;
              -105            }
              -106        }
              -107
              -108        return null;
              -109    }
              -110
              -111    public Set<String> getParameterPermissions() {
              -112        return param.getRequiredPermissions();
              -113    }
              -114
              -115    public boolean isOptional() {
              -116        return param.isOptional();
              -117    }
              -118
              -119    public boolean hasFlag(String flag) {
              -120        return flags.containsKey(flag);
              -121    }
              -122
              -123    public String getFlagValue(String flag, String def) {
              -124        return flags.getOrDefault(flag, def);
              -125    }
              -126
              -127    public Integer getFlagValue(String flag, Integer def) {
              -128        return ACFUtil.parseInt(this.flags.get(flag), def);
              -129    }
              -130
              -131    public Long getFlagValue(String flag, Long def) {
              -132        return ACFUtil.parseLong(this.flags.get(flag), def);
              -133    }
              -134
              -135    public Float getFlagValue(String flag, Float def) {
              -136        return ACFUtil.parseFloat(this.flags.get(flag), def);
              -137    }
              -138
              -139    public Double getFlagValue(String flag, Double def) {
              -140        return ACFUtil.parseDouble(this.flags.get(flag), def);
              -141    }
              -142
              -143    public Integer getIntFlagValue(String flag, Number def) {
              -144        return ACFUtil.parseInt(this.flags.get(flag), def != null ? def.intValue() : null);
              -145    }
              -146
              -147    public Long getLongFlagValue(String flag, Number def) {
              -148        return ACFUtil.parseLong(this.flags.get(flag), def != null ? def.longValue() : null);
              -149    }
              -150
              -151    public Float getFloatFlagValue(String flag, Number def) {
              -152        return ACFUtil.parseFloat(this.flags.get(flag), def != null ? def.floatValue() : null);
              -153    }
              -154
              -155    public Double getDoubleFlagValue(String flag, Number def) {
              -156        return ACFUtil.parseDouble(this.flags.get(flag), def != null ? def.doubleValue() : null);
              -157    }
              -158
              -159    public Boolean getBooleanFlagValue(String flag) {
              -160        return getBooleanFlagValue(flag, false);
              -161    }
              -162
              -163    public Boolean getBooleanFlagValue(String flag, Boolean def) {
              -164        String val = this.flags.get(flag);
              -165        if (val == null) {
              -166            return def;
              -167        }
              -168        return ACFUtil.isTruthy(val);
              -169    }
              -170
              -171    public Double getFlagValue(String flag, Number def) {
              -172        return ACFUtil.parseDouble(this.flags.get(flag), def != null ? def.doubleValue() : null);
              -173    }
              -174
              -175    /**
              -176     * This method will not support annotation processors!! use getAnnotationValue or hasAnnotation
              -177     *
              -178     * @deprecated Use {@link #getAnnotationValue(Class)}
              -179     */
              -180    @Deprecated
              -181    public <T extends Annotation> T getAnnotation(Class<T> cls) {
              -182        return param.getParameter().getAnnotation(cls);
              -183    }
              -184
              -185    public <T extends Annotation> String getAnnotationValue(Class<T> cls) {
              -186        return manager.getAnnotations().getAnnotationValue(param.getParameter(), cls);
              -187    }
              -188
              -189    public <T extends Annotation> String getAnnotationValue(Class<T> cls, int options) {
              -190        return manager.getAnnotations().getAnnotationValue(param.getParameter(), cls, options);
              -191    }
              -192
              -193    public <T extends Annotation> boolean hasAnnotation(Class<T> cls) {
              -194        return manager.getAnnotations().hasAnnotation(param.getParameter(), cls);
              -195    }
              -196
              -197    public RegisteredCommand getCmd() {
              -198        return this.cmd;
              -199    }
              -200
              -201    @UnstableAPI
              -202    CommandParameter getCommandParameter() {
              -203        return this.param;
              -204    }
              -205
              -206    @Deprecated
              -207    public Parameter getParam() {
              -208        return this.param.getParameter();
              -209    }
              -210
              -211    public I getIssuer() {
              -212        return this.issuer;
              -213    }
              -214
              -215    public List<String> getArgs() {
              -216        return this.args;
              -217    }
              -218
              -219    public int getIndex() {
              -220        return this.index;
              -221    }
              -222
              -223    public Map<String, Object> getPassedArgs() {
              -224        return this.passedArgs;
              -225    }
              -226
              -227    public Map<String, String> getFlags() {
              -228        return this.flags;
              -229    }
              -230
              -231    public String joinArgs() {
              -232        return ACFUtil.join(args, " ");
              -233    }
              -234
              -235    public String joinArgs(String sep) {
              -236        return ACFUtil.join(args, sep);
              -237    }
              -238}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import java.lang.annotation.Annotation;
              +027import java.lang.reflect.Parameter;
              +028import java.util.List;
              +029import java.util.Map;
              +030import java.util.Set;
              +031
              +032@SuppressWarnings({"WeakerAccess", "unchecked"})
              +033public class CommandExecutionContext<CEC extends CommandExecutionContext, I extends CommandIssuer> {
              +034    private final RegisteredCommand cmd;
              +035    private final CommandParameter param;
              +036    protected final I issuer;
              +037    private final List<String> args;
              +038    private final int index;
              +039    private final Map<String, Object> passedArgs;
              +040    private final Map<String, String> flags;
              +041    private final CommandManager manager;
              +042
              +043    CommandExecutionContext(RegisteredCommand cmd, CommandParameter param, I sender, List<String> args,
              +044                            int index, Map<String, Object> passedArgs) {
              +045        this.cmd = cmd;
              +046        this.manager = cmd.scope.manager;
              +047        this.param = param;
              +048        this.issuer = sender;
              +049        this.args = args;
              +050        this.index = index;
              +051        this.passedArgs = passedArgs;
              +052        this.flags = param.getFlags();
              +053
              +054    }
              +055
              +056    public String popFirstArg() {
              +057        return !args.isEmpty() ? args.remove(0) : null;
              +058    }
              +059
              +060    public String popLastArg() {
              +061        return !args.isEmpty() ? args.remove(args.size() - 1) : null;
              +062    }
              +063
              +064    public String getFirstArg() {
              +065        return !args.isEmpty() ? args.get(0) : null;
              +066    }
              +067
              +068    public String getLastArg() {
              +069        return !args.isEmpty() ? args.get(args.size() - 1) : null;
              +070    }
              +071
              +072    public boolean isLastArg() {
              +073        return cmd.parameters.length - 1 == index;
              +074    }
              +075
              +076    public int getNumParams() {
              +077        return cmd.parameters.length;
              +078    }
              +079
              +080    public boolean canOverridePlayerContext() {
              +081        return cmd.requiredResolvers >= args.size();
              +082    }
              +083
              +084    public Object getResolvedArg(String arg) {
              +085        return passedArgs.get(arg);
              +086    }
              +087
              +088    public Object getResolvedArg(Class<?>... classes) {
              +089        for (Class<?> clazz : classes) {
              +090            for (Object passedArg : passedArgs.values()) {
              +091                if (clazz.isInstance(passedArg)) {
              +092                    return passedArg;
              +093                }
              +094            }
              +095        }
              +096
              +097        return null;
              +098    }
              +099
              +100    public <T> T getResolvedArg(String key, Class<?>... classes) {
              +101        final Object o = passedArgs.get(key);
              +102        for (Class<?> clazz : classes) {
              +103            if (clazz.isInstance(o)) {
              +104                return (T) o;
              +105            }
              +106        }
              +107
              +108        return null;
              +109    }
              +110
              +111    public Set<String> getParameterPermissions() {
              +112        return param.getRequiredPermissions();
              +113    }
              +114
              +115    public boolean isOptional() {
              +116        return param.isOptional();
              +117    }
              +118
              +119    public boolean hasFlag(String flag) {
              +120        return flags.containsKey(flag);
              +121    }
              +122
              +123    public String getFlagValue(String flag, String def) {
              +124        return flags.getOrDefault(flag, def);
              +125    }
              +126
              +127    public Integer getFlagValue(String flag, Integer def) {
              +128        return ACFUtil.parseInt(this.flags.get(flag), def);
              +129    }
              +130
              +131    public Long getFlagValue(String flag, Long def) {
              +132        return ACFUtil.parseLong(this.flags.get(flag), def);
              +133    }
              +134
              +135    public Float getFlagValue(String flag, Float def) {
              +136        return ACFUtil.parseFloat(this.flags.get(flag), def);
              +137    }
              +138
              +139    public Double getFlagValue(String flag, Double def) {
              +140        return ACFUtil.parseDouble(this.flags.get(flag), def);
              +141    }
              +142
              +143    public Integer getIntFlagValue(String flag, Number def) {
              +144        return ACFUtil.parseInt(this.flags.get(flag), def != null ? def.intValue() : null);
              +145    }
              +146
              +147    public Long getLongFlagValue(String flag, Number def) {
              +148        return ACFUtil.parseLong(this.flags.get(flag), def != null ? def.longValue() : null);
              +149    }
              +150
              +151    public Float getFloatFlagValue(String flag, Number def) {
              +152        return ACFUtil.parseFloat(this.flags.get(flag), def != null ? def.floatValue() : null);
              +153    }
              +154
              +155    public Double getDoubleFlagValue(String flag, Number def) {
              +156        return ACFUtil.parseDouble(this.flags.get(flag), def != null ? def.doubleValue() : null);
              +157    }
              +158
              +159    public Boolean getBooleanFlagValue(String flag) {
              +160        return getBooleanFlagValue(flag, false);
              +161    }
              +162
              +163    public Boolean getBooleanFlagValue(String flag, Boolean def) {
              +164        String val = this.flags.get(flag);
              +165        if (val == null) {
              +166            return def;
              +167        }
              +168        return ACFUtil.isTruthy(val);
              +169    }
              +170
              +171    public Double getFlagValue(String flag, Number def) {
              +172        return ACFUtil.parseDouble(this.flags.get(flag), def != null ? def.doubleValue() : null);
              +173    }
              +174
              +175    /**
              +176     * This method will not support annotation processors!! use getAnnotationValue or hasAnnotation
              +177     *
              +178     * @deprecated Use {@link #getAnnotationValue(Class)}
              +179     */
              +180    @Deprecated
              +181    public <T extends Annotation> T getAnnotation(Class<T> cls) {
              +182        return param.getParameter().getAnnotation(cls);
              +183    }
              +184
              +185    public <T extends Annotation> String getAnnotationValue(Class<T> cls) {
              +186        return manager.getAnnotations().getAnnotationValue(param.getParameter(), cls);
              +187    }
              +188
              +189    public <T extends Annotation> String getAnnotationValue(Class<T> cls, int options) {
              +190        return manager.getAnnotations().getAnnotationValue(param.getParameter(), cls, options);
              +191    }
              +192
              +193    public <T extends Annotation> boolean hasAnnotation(Class<T> cls) {
              +194        return manager.getAnnotations().hasAnnotation(param.getParameter(), cls);
              +195    }
              +196
              +197    public RegisteredCommand getCmd() {
              +198        return this.cmd;
              +199    }
              +200
              +201    @UnstableAPI
              +202    CommandParameter getCommandParameter() {
              +203        return this.param;
              +204    }
              +205
              +206    @Deprecated
              +207    public Parameter getParam() {
              +208        return this.param.getParameter();
              +209    }
              +210
              +211    public I getIssuer() {
              +212        return this.issuer;
              +213    }
              +214
              +215    public List<String> getArgs() {
              +216        return this.args;
              +217    }
              +218
              +219    public int getIndex() {
              +220        return this.index;
              +221    }
              +222
              +223    public Map<String, Object> getPassedArgs() {
              +224        return this.passedArgs;
              +225    }
              +226
              +227    public Map<String, String> getFlags() {
              +228        return this.flags;
              +229    }
              +230
              +231    public String joinArgs() {
              +232        return ACFUtil.join(args, " ");
              +233    }
              +234
              +235    public String joinArgs(String sep) {
              +236        return ACFUtil.join(args, sep);
              +237    }
              +238}
               
               
               
              @@ -306,5 +307,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandHelp.html b/docs/acf-core/src-html/co/aikar/commands/CommandHelp.html index ae313878..59fa2309 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandHelp.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandHelp.html @@ -1,267 +1,268 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import com.google.common.collect.SetMultimap;
              -027
              -028import java.util.ArrayList;
              -029import java.util.Comparator;
              -030import java.util.HashSet;
              -031import java.util.Iterator;
              -032import java.util.List;
              -033import java.util.Set;
              -034import java.util.regex.Pattern;
              -035import java.util.stream.Collectors;
              -036
              -037@SuppressWarnings("WeakerAccess")
              -038public class CommandHelp {
              -039    private final CommandManager manager;
              -040    private final CommandIssuer issuer;
              -041    private final List<HelpEntry> helpEntries = new ArrayList<>();
              -042    private final String commandName;
              -043    final String commandPrefix;
              -044    private int page = 1;
              -045    private int perPage;
              -046    List<String> search;
              -047    private Set<HelpEntry> selectedEntry = new HashSet<>();
              -048    private int totalResults;
              -049    private int totalPages;
              -050    private boolean lastPage;
              -051
              -052    public CommandHelp(CommandManager manager, RootCommand rootCommand, CommandIssuer issuer) {
              -053        this.manager = manager;
              -054        this.issuer = issuer;
              -055        this.perPage = manager.defaultHelpPerPage;
              -056        this.commandPrefix = manager.getCommandPrefix(issuer);
              -057        this.commandName = rootCommand.getCommandName();
              -058
              -059
              -060        SetMultimap<String, RegisteredCommand> subCommands = rootCommand.getSubCommands();
              -061        Set<RegisteredCommand> seen = new HashSet<>();
              -062
              -063        if (!rootCommand.getDefCommand().hasHelpCommand) {
              -064            RegisteredCommand defCommand = rootCommand.getDefaultRegisteredCommand();
              -065            if (defCommand != null) {
              -066                helpEntries.add(new HelpEntry(this, defCommand));
              -067                seen.add(defCommand);
              -068            }
              -069        }
              -070
              -071        subCommands.entries().forEach(e -> {
              -072            String key = e.getKey();
              -073            if (key.equals(BaseCommand.DEFAULT) || key.equals(BaseCommand.CATCHUNKNOWN)) {
              -074                return;
              -075            }
              -076
              -077            RegisteredCommand regCommand = e.getValue();
              -078
              -079            if (!regCommand.isPrivate && regCommand.hasPermission(issuer) && !seen.contains(regCommand)) {
              -080                this.helpEntries.add(new HelpEntry(this, regCommand));
              -081                seen.add(regCommand);
              -082            }
              -083        });
              -084    }
              -085
              -086    @UnstableAPI // Not sure on this one yet even when API becomes unstable
              -087    protected void updateSearchScore(HelpEntry help) {
              -088        if (this.search == null || this.search.isEmpty()) {
              -089            help.setSearchScore(1);
              -090            return;
              -091        }
              -092        final RegisteredCommand<?> cmd = help.getRegisteredCommand();
              -093
              -094        int searchScore = 0;
              -095        for (String word : this.search) {
              -096            Pattern pattern = Pattern.compile(".*" + Pattern.quote(word) + ".*", Pattern.CASE_INSENSITIVE);
              -097            for (String subCmd : cmd.registeredSubcommands) {
              -098                Pattern subCmdPattern = Pattern.compile(".*" + Pattern.quote(subCmd) + ".*", Pattern.CASE_INSENSITIVE);
              -099                if (pattern.matcher(subCmd).matches()) {
              -100                    searchScore += 3;
              -101                } else if (subCmdPattern.matcher(word).matches()) {
              -102                    searchScore++;
              -103                }
              -104            }
              -105
              -106
              -107            if (pattern.matcher(help.getDescription()).matches()) {
              -108                searchScore += 2;
              -109            }
              -110            if (pattern.matcher(help.getParameterSyntax()).matches()) {
              -111                searchScore++;
              -112            }
              -113            if (help.getSearchTags() != null && pattern.matcher(help.getSearchTags()).matches()) {
              -114                searchScore += 2;
              -115            }
              -116        }
              -117        help.setSearchScore(searchScore);
              -118    }
              -119
              -120    public CommandManager getManager() {
              -121        return manager;
              -122    }
              -123
              -124    public boolean testExactMatch(String command) {
              -125        selectedEntry.clear();
              -126        for (HelpEntry helpEntry : helpEntries) {
              -127            if (helpEntry.getCommand().endsWith(" " + command)) {
              -128                selectedEntry.add(helpEntry);
              -129            }
              -130        }
              -131        return !selectedEntry.isEmpty();
              -132    }
              -133
              -134    public void showHelp() {
              -135        showHelp(issuer);
              -136    }
              -137
              -138    public void showHelp(CommandIssuer issuer) {
              -139        CommandHelpFormatter formatter = manager.getHelpFormatter();
              -140        if (!selectedEntry.isEmpty()) {
              -141            HelpEntry first = ACFUtil.getFirstElement(selectedEntry);
              -142            formatter.printDetailedHelpHeader(this, issuer, first);
              -143
              -144            for (HelpEntry helpEntry : selectedEntry) {
              -145                formatter.showDetailedHelp(this, helpEntry);
              -146            }
              -147
              -148            formatter.printDetailedHelpFooter(this, issuer, first);
              -149            return;
              -150        }
              -151
              -152        List<HelpEntry> helpEntries = getHelpEntries().stream().filter(HelpEntry::shouldShow).collect(Collectors.toList());
              -153        Iterator<HelpEntry> results = helpEntries.stream()
              -154                .sorted(Comparator.comparingInt(helpEntry -> helpEntry.getSearchScore() * -1)).iterator();
              -155        if (!results.hasNext()) {
              -156            issuer.sendMessage(MessageType.ERROR, MessageKeys.NO_COMMAND_MATCHED_SEARCH, "{search}", ACFUtil.join(this.search, " "));
              -157            helpEntries = getHelpEntries();
              -158            results = helpEntries.iterator();
              -159        }
              -160        this.totalResults = helpEntries.size();
              -161        int min = (this.page - 1) * this.perPage; // TODO: per page configurable?
              -162        int max = min + this.perPage;
              -163        this.totalPages = (int) Math.ceil((float) totalResults / (float) this.perPage);
              -164        int i = 0;
              -165        if (min >= totalResults) {
              -166            issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_NO_RESULTS);
              -167            return;
              -168        }
              -169
              -170        List<HelpEntry> printEntries = new ArrayList<>();
              -171        while (results.hasNext()) {
              -172            HelpEntry e = results.next();
              -173            if (i >= max) {
              -174                break;
              -175            }
              -176            if (i++ < min) {
              -177                continue;
              -178            }
              -179            printEntries.add(e);
              -180        }
              -181        this.lastPage = max >= totalResults;
              -182
              -183        if (search == null) {
              -184            formatter.showAllResults(this, printEntries);
              -185        } else {
              -186            formatter.showSearchResults(this, printEntries);
              -187        }
              -188
              -189    }
              -190
              -191    public List<HelpEntry> getHelpEntries() {
              -192        return helpEntries;
              -193    }
              -194
              -195    public void setPerPage(int perPage) {
              -196        this.perPage = perPage;
              -197    }
              -198
              -199    public void setPage(int page) {
              -200        this.page = page;
              -201    }
              -202
              -203    public void setPage(int page, int perPage) {
              -204        this.setPage(page);
              -205        this.setPerPage(perPage);
              -206    }
              -207
              -208    public void setSearch(List<String> search) {
              -209        this.search = search;
              -210        getHelpEntries().forEach(this::updateSearchScore);
              -211    }
              -212
              -213    public CommandIssuer getIssuer() {
              -214        return issuer;
              -215    }
              -216
              -217    public String getCommandName() {
              -218        return commandName;
              -219    }
              -220
              -221    public String getCommandPrefix() {
              -222        return commandPrefix;
              -223    }
              -224
              -225    public int getPage() {
              -226        return page;
              -227    }
              -228
              -229    public int getPerPage() {
              -230        return perPage;
              -231    }
              -232
              -233    public List<String> getSearch() {
              -234        return search;
              -235    }
              -236
              -237    public Set<HelpEntry> getSelectedEntry() {
              -238        return selectedEntry;
              -239    }
              -240
              -241    public int getTotalResults() {
              -242        return totalResults;
              -243    }
              -244
              -245    public int getTotalPages() {
              -246        return totalPages;
              -247    }
              -248
              -249    public boolean isOnlyPage() {
              -250        return this.page == 1 && lastPage;
              -251    }
              -252
              -253    public boolean isLastPage() {
              -254        return lastPage;
              -255    }
              -256}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import com.google.common.collect.SetMultimap;
              +027
              +028import java.util.ArrayList;
              +029import java.util.Comparator;
              +030import java.util.HashSet;
              +031import java.util.Iterator;
              +032import java.util.List;
              +033import java.util.Set;
              +034import java.util.regex.Pattern;
              +035import java.util.stream.Collectors;
              +036
              +037@SuppressWarnings("WeakerAccess")
              +038public class CommandHelp {
              +039    private final CommandManager manager;
              +040    private final CommandIssuer issuer;
              +041    private final List<HelpEntry> helpEntries = new ArrayList<>();
              +042    private final String commandName;
              +043    final String commandPrefix;
              +044    private int page = 1;
              +045    private int perPage;
              +046    List<String> search;
              +047    private Set<HelpEntry> selectedEntry = new HashSet<>();
              +048    private int totalResults;
              +049    private int totalPages;
              +050    private boolean lastPage;
              +051
              +052    public CommandHelp(CommandManager manager, RootCommand rootCommand, CommandIssuer issuer) {
              +053        this.manager = manager;
              +054        this.issuer = issuer;
              +055        this.perPage = manager.defaultHelpPerPage;
              +056        this.commandPrefix = manager.getCommandPrefix(issuer);
              +057        this.commandName = rootCommand.getCommandName();
              +058
              +059
              +060        SetMultimap<String, RegisteredCommand> subCommands = rootCommand.getSubCommands();
              +061        Set<RegisteredCommand> seen = new HashSet<>();
              +062
              +063        if (!rootCommand.getDefCommand().hasHelpCommand) {
              +064            RegisteredCommand defCommand = rootCommand.getDefaultRegisteredCommand();
              +065            if (defCommand != null) {
              +066                helpEntries.add(new HelpEntry(this, defCommand));
              +067                seen.add(defCommand);
              +068            }
              +069        }
              +070
              +071        subCommands.entries().forEach(e -> {
              +072            String key = e.getKey();
              +073            if (key.equals(BaseCommand.DEFAULT) || key.equals(BaseCommand.CATCHUNKNOWN)) {
              +074                return;
              +075            }
              +076
              +077            RegisteredCommand regCommand = e.getValue();
              +078
              +079            if (!regCommand.isPrivate && regCommand.hasPermission(issuer) && !seen.contains(regCommand)) {
              +080                this.helpEntries.add(new HelpEntry(this, regCommand));
              +081                seen.add(regCommand);
              +082            }
              +083        });
              +084    }
              +085
              +086    @UnstableAPI // Not sure on this one yet even when API becomes unstable
              +087    protected void updateSearchScore(HelpEntry help) {
              +088        if (this.search == null || this.search.isEmpty()) {
              +089            help.setSearchScore(1);
              +090            return;
              +091        }
              +092        final RegisteredCommand<?> cmd = help.getRegisteredCommand();
              +093
              +094        int searchScore = 0;
              +095        for (String word : this.search) {
              +096            Pattern pattern = Pattern.compile(".*" + Pattern.quote(word) + ".*", Pattern.CASE_INSENSITIVE);
              +097            for (String subCmd : cmd.registeredSubcommands) {
              +098                Pattern subCmdPattern = Pattern.compile(".*" + Pattern.quote(subCmd) + ".*", Pattern.CASE_INSENSITIVE);
              +099                if (pattern.matcher(subCmd).matches()) {
              +100                    searchScore += 3;
              +101                } else if (subCmdPattern.matcher(word).matches()) {
              +102                    searchScore++;
              +103                }
              +104            }
              +105
              +106
              +107            if (pattern.matcher(help.getDescription()).matches()) {
              +108                searchScore += 2;
              +109            }
              +110            if (pattern.matcher(help.getParameterSyntax()).matches()) {
              +111                searchScore++;
              +112            }
              +113            if (help.getSearchTags() != null && pattern.matcher(help.getSearchTags()).matches()) {
              +114                searchScore += 2;
              +115            }
              +116        }
              +117        help.setSearchScore(searchScore);
              +118    }
              +119
              +120    public CommandManager getManager() {
              +121        return manager;
              +122    }
              +123
              +124    public boolean testExactMatch(String command) {
              +125        selectedEntry.clear();
              +126        for (HelpEntry helpEntry : helpEntries) {
              +127            if (helpEntry.getCommand().endsWith(" " + command)) {
              +128                selectedEntry.add(helpEntry);
              +129            }
              +130        }
              +131        return !selectedEntry.isEmpty();
              +132    }
              +133
              +134    public void showHelp() {
              +135        showHelp(issuer);
              +136    }
              +137
              +138    public void showHelp(CommandIssuer issuer) {
              +139        CommandHelpFormatter formatter = manager.getHelpFormatter();
              +140        if (!selectedEntry.isEmpty()) {
              +141            HelpEntry first = ACFUtil.getFirstElement(selectedEntry);
              +142            formatter.printDetailedHelpHeader(this, issuer, first);
              +143
              +144            for (HelpEntry helpEntry : selectedEntry) {
              +145                formatter.showDetailedHelp(this, helpEntry);
              +146            }
              +147
              +148            formatter.printDetailedHelpFooter(this, issuer, first);
              +149            return;
              +150        }
              +151
              +152        List<HelpEntry> helpEntries = getHelpEntries().stream().filter(HelpEntry::shouldShow).collect(Collectors.toList());
              +153        Iterator<HelpEntry> results = helpEntries.stream()
              +154                .sorted(Comparator.comparingInt(helpEntry -> helpEntry.getSearchScore() * -1)).iterator();
              +155        if (!results.hasNext()) {
              +156            issuer.sendMessage(MessageType.ERROR, MessageKeys.NO_COMMAND_MATCHED_SEARCH, "{search}", ACFUtil.join(this.search, " "));
              +157            helpEntries = getHelpEntries();
              +158            results = helpEntries.iterator();
              +159        }
              +160        this.totalResults = helpEntries.size();
              +161        int min = (this.page - 1) * this.perPage; // TODO: per page configurable?
              +162        int max = min + this.perPage;
              +163        this.totalPages = (int) Math.ceil((float) totalResults / (float) this.perPage);
              +164        int i = 0;
              +165        if (min >= totalResults) {
              +166            issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_NO_RESULTS);
              +167            return;
              +168        }
              +169
              +170        List<HelpEntry> printEntries = new ArrayList<>();
              +171        while (results.hasNext()) {
              +172            HelpEntry e = results.next();
              +173            if (i >= max) {
              +174                break;
              +175            }
              +176            if (i++ < min) {
              +177                continue;
              +178            }
              +179            printEntries.add(e);
              +180        }
              +181        this.lastPage = max >= totalResults;
              +182
              +183        if (search == null) {
              +184            formatter.showAllResults(this, printEntries);
              +185        } else {
              +186            formatter.showSearchResults(this, printEntries);
              +187        }
              +188
              +189    }
              +190
              +191    public List<HelpEntry> getHelpEntries() {
              +192        return helpEntries;
              +193    }
              +194
              +195    public void setPerPage(int perPage) {
              +196        this.perPage = perPage;
              +197    }
              +198
              +199    public void setPage(int page) {
              +200        this.page = page;
              +201    }
              +202
              +203    public void setPage(int page, int perPage) {
              +204        this.setPage(page);
              +205        this.setPerPage(perPage);
              +206    }
              +207
              +208    public void setSearch(List<String> search) {
              +209        this.search = search;
              +210        getHelpEntries().forEach(this::updateSearchScore);
              +211    }
              +212
              +213    public CommandIssuer getIssuer() {
              +214        return issuer;
              +215    }
              +216
              +217    public String getCommandName() {
              +218        return commandName;
              +219    }
              +220
              +221    public String getCommandPrefix() {
              +222        return commandPrefix;
              +223    }
              +224
              +225    public int getPage() {
              +226        return page;
              +227    }
              +228
              +229    public int getPerPage() {
              +230        return perPage;
              +231    }
              +232
              +233    public List<String> getSearch() {
              +234        return search;
              +235    }
              +236
              +237    public Set<HelpEntry> getSelectedEntry() {
              +238        return selectedEntry;
              +239    }
              +240
              +241    public int getTotalResults() {
              +242        return totalResults;
              +243    }
              +244
              +245    public int getTotalPages() {
              +246        return totalPages;
              +247    }
              +248
              +249    public boolean isOnlyPage() {
              +250        return this.page == 1 && lastPage;
              +251    }
              +252
              +253    public boolean isLastPage() {
              +254        return lastPage;
              +255    }
              +256}
               
               
               
              @@ -324,5 +325,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandHelpFormatter.html b/docs/acf-core/src-html/co/aikar/commands/CommandHelpFormatter.html index 80c43736..8ed8eea1 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandHelpFormatter.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandHelpFormatter.html @@ -1,215 +1,216 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import org.jetbrains.annotations.NotNull;
              -027
              -028import java.util.List;
              -029
              -030public class CommandHelpFormatter {
              -031
              -032    private final CommandManager manager;
              -033
              -034    public CommandHelpFormatter(CommandManager manager) {
              -035        this.manager = manager;
              -036    }
              -037
              -038
              -039    public void showAllResults(CommandHelp commandHelp, List<HelpEntry> entries) {
              -040        CommandIssuer issuer = commandHelp.getIssuer();
              -041        printHelpHeader(commandHelp, issuer);
              -042        for (HelpEntry e : entries) {
              -043            printHelpCommand(commandHelp, issuer, e);
              -044        }
              -045        printHelpFooter(commandHelp, issuer);
              -046    }
              -047
              -048    public void showSearchResults(CommandHelp commandHelp, List<HelpEntry> entries) {
              -049        CommandIssuer issuer = commandHelp.getIssuer();
              -050        printSearchHeader(commandHelp, issuer);
              -051        for (HelpEntry e : entries) {
              -052            printSearchEntry(commandHelp, issuer, e);
              -053        }
              -054        printSearchFooter(commandHelp, issuer);
              -055    }
              -056
              -057    public void showDetailedHelp(CommandHelp commandHelp, HelpEntry entry) {
              -058        CommandIssuer issuer = commandHelp.getIssuer();
              -059
              -060        // normal help line
              -061        printDetailedHelpCommand(commandHelp, issuer, entry);
              -062
              -063        // additionally detailed help for params
              -064        for (CommandParameter param : entry.getParameters()) {
              -065            String description = param.getDescription();
              -066            if (description != null && !description.isEmpty()) {
              -067                printDetailedParameter(commandHelp, issuer, entry, param);
              -068            }
              -069        }
              -070    }
              -071
              -072    // ########
              -073    // # help #
              -074    // ########
              -075
              -076    public void printHelpHeader(CommandHelp help, CommandIssuer issuer) {
              -077        issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_HEADER, getHeaderFooterFormatReplacements(help));
              -078    }
              -079
              -080    public void printHelpCommand(CommandHelp help, CommandIssuer issuer, HelpEntry entry) {
              -081        String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getEntryFormatReplacements(help, entry));
              -082        for (String msg : ACFPatterns.NEWLINE.split(formatted)) {
              -083            issuer.sendMessageInternal(ACFUtil.rtrim(msg));
              -084        }
              -085    }
              -086
              -087    public void printHelpFooter(CommandHelp help, CommandIssuer issuer) {
              -088        if (help.isOnlyPage()) {
              -089            return;
              -090        }
              -091        issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_PAGE_INFORMATION, getHeaderFooterFormatReplacements(help));
              -092    }
              -093
              -094    // ##########
              -095    // # search #
              -096    // ##########
              -097
              -098    public void printSearchHeader(CommandHelp help, CommandIssuer issuer) {
              -099        issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_SEARCH_HEADER, getHeaderFooterFormatReplacements(help));
              -100    }
              -101
              -102    public void printSearchEntry(CommandHelp help, CommandIssuer issuer, HelpEntry page) {
              -103        String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getEntryFormatReplacements(help, page));
              -104        for (String msg : ACFPatterns.NEWLINE.split(formatted)) {
              -105            issuer.sendMessageInternal(ACFUtil.rtrim(msg));
              -106        }
              -107    }
              -108
              -109    public void printSearchFooter(CommandHelp help, CommandIssuer issuer) {
              -110        if (help.isOnlyPage()) {
              -111            return;
              -112        }
              -113        issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_PAGE_INFORMATION, getHeaderFooterFormatReplacements(help));
              -114    }
              -115
              -116
              -117    // ############
              -118    // # detailed #
              -119    // ############
              -120
              -121    public void printDetailedHelpHeader(CommandHelp help, CommandIssuer issuer, HelpEntry entry) {
              -122        issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_DETAILED_HEADER,
              -123                "{command}", entry.getCommand(),
              -124                "{commandprefix}", help.getCommandPrefix()
              -125        );
              -126    }
              -127
              -128
              -129    public void printDetailedHelpCommand(CommandHelp help, CommandIssuer issuer, HelpEntry entry) {
              -130        String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_DETAILED_COMMAND_FORMAT, getEntryFormatReplacements(help, entry));
              -131        for (String msg : ACFPatterns.NEWLINE.split(formatted)) {
              -132            issuer.sendMessageInternal(ACFUtil.rtrim(msg));
              -133        }
              -134    }
              -135
              -136    public void printDetailedParameter(CommandHelp help, CommandIssuer issuer, HelpEntry entry, CommandParameter param) {
              -137        String formattedMsg = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_DETAILED_PARAMETER_FORMAT, getParameterFormatReplacements(help, param, entry));
              -138        for (String msg : ACFPatterns.NEWLINE.split(formattedMsg)) {
              -139            issuer.sendMessageInternal(ACFUtil.rtrim(msg));
              -140        }
              -141    }
              -142
              -143    public void printDetailedHelpFooter(CommandHelp help, CommandIssuer issuer, HelpEntry entry) {
              -144        // default doesn't have a footer
              -145    }
              -146
              -147    /**
              -148     * Override this to control replacements
              -149     *
              -150     * @param help
              -151     * @return
              -152     */
              -153    public String[] getHeaderFooterFormatReplacements(CommandHelp help) {
              -154        return new String[]{
              -155                "{search}", help.search != null ? String.join(" ", help.search) : "",
              -156                "{command}", help.getCommandName(),
              -157                "{commandprefix}", help.getCommandPrefix(),
              -158                "{rootcommand}", help.getCommandName(),
              -159                "{page}", "" + help.getPage(),
              -160                "{totalpages}", "" + help.getTotalPages(),
              -161                "{results}", "" + help.getTotalResults()
              -162        };
              -163    }
              -164
              -165    /**
              -166     * Override this to control replacements
              -167     *
              -168     * @param help
              -169     * @param entry
              -170     * @return
              -171     */
              -172    public String[] getEntryFormatReplacements(CommandHelp help, HelpEntry entry) {
              -173        //{command} {parameters} {separator} {description}
              -174        return new String[]{
              -175                "{command}", entry.getCommand(),
              -176                "{commandprefix}", help.getCommandPrefix(),
              -177                "{parameters}", entry.getParameterSyntax(),
              -178                "{separator}", entry.getDescription().isEmpty() ? "" : "-",
              -179                "{description}", entry.getDescription()
              -180        };
              -181    }
              -182
              -183    /**
              -184     * Override this to control replacements
              -185     *
              -186     * @param help
              -187     * @param param
              -188     * @param entry
              -189     * @return
              -190     */
              -191    @NotNull
              -192    public String[] getParameterFormatReplacements(CommandHelp help, CommandParameter param, HelpEntry entry) {
              -193        //{name} {description}
              -194        return new String[]{
              -195                "{name}", param.getName(),
              -196                "{syntaxorname}", ACFUtil.nullDefault(param.getSyntax(), param.getName()),
              -197                "{syntax}", ACFUtil.nullDefault(param.getSyntax(), ""),
              -198                "{description}", ACFUtil.nullDefault(param.getDescription(), ""),
              -199                "{command}", help.getCommandName(),
              -200                "{fullcommand}", entry.getCommand(),
              -201                "{commandprefix}", help.getCommandPrefix()
              -202        };
              -203    }
              -204}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import org.jetbrains.annotations.NotNull;
              +027
              +028import java.util.List;
              +029
              +030public class CommandHelpFormatter {
              +031
              +032    private final CommandManager manager;
              +033
              +034    public CommandHelpFormatter(CommandManager manager) {
              +035        this.manager = manager;
              +036    }
              +037
              +038
              +039    public void showAllResults(CommandHelp commandHelp, List<HelpEntry> entries) {
              +040        CommandIssuer issuer = commandHelp.getIssuer();
              +041        printHelpHeader(commandHelp, issuer);
              +042        for (HelpEntry e : entries) {
              +043            printHelpCommand(commandHelp, issuer, e);
              +044        }
              +045        printHelpFooter(commandHelp, issuer);
              +046    }
              +047
              +048    public void showSearchResults(CommandHelp commandHelp, List<HelpEntry> entries) {
              +049        CommandIssuer issuer = commandHelp.getIssuer();
              +050        printSearchHeader(commandHelp, issuer);
              +051        for (HelpEntry e : entries) {
              +052            printSearchEntry(commandHelp, issuer, e);
              +053        }
              +054        printSearchFooter(commandHelp, issuer);
              +055    }
              +056
              +057    public void showDetailedHelp(CommandHelp commandHelp, HelpEntry entry) {
              +058        CommandIssuer issuer = commandHelp.getIssuer();
              +059
              +060        // normal help line
              +061        printDetailedHelpCommand(commandHelp, issuer, entry);
              +062
              +063        // additionally detailed help for params
              +064        for (CommandParameter param : entry.getParameters()) {
              +065            String description = param.getDescription();
              +066            if (description != null && !description.isEmpty()) {
              +067                printDetailedParameter(commandHelp, issuer, entry, param);
              +068            }
              +069        }
              +070    }
              +071
              +072    // ########
              +073    // # help #
              +074    // ########
              +075
              +076    public void printHelpHeader(CommandHelp help, CommandIssuer issuer) {
              +077        issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_HEADER, getHeaderFooterFormatReplacements(help));
              +078    }
              +079
              +080    public void printHelpCommand(CommandHelp help, CommandIssuer issuer, HelpEntry entry) {
              +081        String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getEntryFormatReplacements(help, entry));
              +082        for (String msg : ACFPatterns.NEWLINE.split(formatted)) {
              +083            issuer.sendMessageInternal(ACFUtil.rtrim(msg));
              +084        }
              +085    }
              +086
              +087    public void printHelpFooter(CommandHelp help, CommandIssuer issuer) {
              +088        if (help.isOnlyPage()) {
              +089            return;
              +090        }
              +091        issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_PAGE_INFORMATION, getHeaderFooterFormatReplacements(help));
              +092    }
              +093
              +094    // ##########
              +095    // # search #
              +096    // ##########
              +097
              +098    public void printSearchHeader(CommandHelp help, CommandIssuer issuer) {
              +099        issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_SEARCH_HEADER, getHeaderFooterFormatReplacements(help));
              +100    }
              +101
              +102    public void printSearchEntry(CommandHelp help, CommandIssuer issuer, HelpEntry page) {
              +103        String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getEntryFormatReplacements(help, page));
              +104        for (String msg : ACFPatterns.NEWLINE.split(formatted)) {
              +105            issuer.sendMessageInternal(ACFUtil.rtrim(msg));
              +106        }
              +107    }
              +108
              +109    public void printSearchFooter(CommandHelp help, CommandIssuer issuer) {
              +110        if (help.isOnlyPage()) {
              +111            return;
              +112        }
              +113        issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_PAGE_INFORMATION, getHeaderFooterFormatReplacements(help));
              +114    }
              +115
              +116
              +117    // ############
              +118    // # detailed #
              +119    // ############
              +120
              +121    public void printDetailedHelpHeader(CommandHelp help, CommandIssuer issuer, HelpEntry entry) {
              +122        issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_DETAILED_HEADER,
              +123                "{command}", entry.getCommand(),
              +124                "{commandprefix}", help.getCommandPrefix()
              +125        );
              +126    }
              +127
              +128
              +129    public void printDetailedHelpCommand(CommandHelp help, CommandIssuer issuer, HelpEntry entry) {
              +130        String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_DETAILED_COMMAND_FORMAT, getEntryFormatReplacements(help, entry));
              +131        for (String msg : ACFPatterns.NEWLINE.split(formatted)) {
              +132            issuer.sendMessageInternal(ACFUtil.rtrim(msg));
              +133        }
              +134    }
              +135
              +136    public void printDetailedParameter(CommandHelp help, CommandIssuer issuer, HelpEntry entry, CommandParameter param) {
              +137        String formattedMsg = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_DETAILED_PARAMETER_FORMAT, getParameterFormatReplacements(help, param, entry));
              +138        for (String msg : ACFPatterns.NEWLINE.split(formattedMsg)) {
              +139            issuer.sendMessageInternal(ACFUtil.rtrim(msg));
              +140        }
              +141    }
              +142
              +143    public void printDetailedHelpFooter(CommandHelp help, CommandIssuer issuer, HelpEntry entry) {
              +144        // default doesn't have a footer
              +145    }
              +146
              +147    /**
              +148     * Override this to control replacements
              +149     *
              +150     * @param help
              +151     * @return
              +152     */
              +153    public String[] getHeaderFooterFormatReplacements(CommandHelp help) {
              +154        return new String[]{
              +155                "{search}", help.search != null ? String.join(" ", help.search) : "",
              +156                "{command}", help.getCommandName(),
              +157                "{commandprefix}", help.getCommandPrefix(),
              +158                "{rootcommand}", help.getCommandName(),
              +159                "{page}", "" + help.getPage(),
              +160                "{totalpages}", "" + help.getTotalPages(),
              +161                "{results}", "" + help.getTotalResults()
              +162        };
              +163    }
              +164
              +165    /**
              +166     * Override this to control replacements
              +167     *
              +168     * @param help
              +169     * @param entry
              +170     * @return
              +171     */
              +172    public String[] getEntryFormatReplacements(CommandHelp help, HelpEntry entry) {
              +173        //{command} {parameters} {separator} {description}
              +174        return new String[]{
              +175                "{command}", entry.getCommand(),
              +176                "{commandprefix}", help.getCommandPrefix(),
              +177                "{parameters}", entry.getParameterSyntax(),
              +178                "{separator}", entry.getDescription().isEmpty() ? "" : "-",
              +179                "{description}", entry.getDescription()
              +180        };
              +181    }
              +182
              +183    /**
              +184     * Override this to control replacements
              +185     *
              +186     * @param help
              +187     * @param param
              +188     * @param entry
              +189     * @return
              +190     */
              +191    @NotNull
              +192    public String[] getParameterFormatReplacements(CommandHelp help, CommandParameter param, HelpEntry entry) {
              +193        //{name} {description}
              +194        return new String[]{
              +195                "{name}", param.getName(),
              +196                "{syntaxorname}", ACFUtil.nullDefault(param.getSyntax(), param.getName()),
              +197                "{syntax}", ACFUtil.nullDefault(param.getSyntax(), ""),
              +198                "{description}", ACFUtil.nullDefault(param.getDescription(), ""),
              +199                "{command}", help.getCommandName(),
              +200                "{fullcommand}", entry.getCommand(),
              +201                "{commandprefix}", help.getCommandPrefix()
              +202        };
              +203    }
              +204}
               
               
               
              @@ -272,5 +273,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandIssuer.html b/docs/acf-core/src-html/co/aikar/commands/CommandIssuer.html index 62edfc0a..c845537a 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandIssuer.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandIssuer.html @@ -1,110 +1,111 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.locales.MessageKey;
              -027import co.aikar.locales.MessageKeyProvider;
              -028import org.jetbrains.annotations.NotNull;
              -029
              -030import java.util.UUID;
              -031
              -032public interface CommandIssuer {
              -033    /**
              -034     * Gets the issuer in the platforms native object
              -035     * @param <T>
              -036     * @return
              -037     */
              -038    <T> T getIssuer();
              -039
              -040    CommandManager getManager();
              -041
              -042    /**
              -043     * Is this issue a player, or server/console sender
              -044     * @return
              -045     */
              -046    boolean isPlayer();
              -047
              -048    /**
              -049     * Send the Command Issuer a message
              -050     * @param message
              -051     */
              -052    default void sendMessage(String message) {
              -053        getManager().sendMessage(this, MessageType.INFO, MessageKeys.INFO_MESSAGE, "{message}", message);
              -054    }
              -055
              -056    /**
              -057     * @return the unique id of that issuer
              -058     */
              -059    @NotNull UUID getUniqueId();
              -060
              -061    /**
              -062     * Has permission node
              -063     * @param permission
              -064     * @return
              -065     */
              -066    boolean hasPermission(String permission);
              -067
              -068    default void sendError(MessageKeyProvider key, String... replacements) {
              -069        sendMessage(MessageType.ERROR, key.getMessageKey(), replacements);
              -070    }
              -071    default void sendSyntax(MessageKeyProvider key, String... replacements) {
              -072        sendMessage(MessageType.SYNTAX, key.getMessageKey(), replacements);
              -073    }
              -074    default void sendInfo(MessageKeyProvider key, String... replacements) {
              -075        sendMessage(MessageType.INFO, key.getMessageKey(), replacements);
              -076    }
              -077    default void sendError(MessageKey key, String... replacements) {
              -078        sendMessage(MessageType.ERROR, key, replacements);
              -079    }
              -080    default void sendSyntax(MessageKey key, String... replacements) {
              -081        sendMessage(MessageType.SYNTAX, key, replacements);
              -082    }
              -083    default void sendInfo(MessageKey key, String... replacements) {
              -084        sendMessage(MessageType.INFO, key, replacements);
              -085    }
              -086    default void sendMessage(MessageType type, MessageKeyProvider key, String... replacements) {
              -087        sendMessage(type, key.getMessageKey(), replacements);
              -088    }
              -089    default void sendMessage(MessageType type, MessageKey key, String... replacements) {
              -090        getManager().sendMessage(this, type, key, replacements);
              -091    }
              -092
              -093    /**
              -094     * @deprecated Do not call this, for internal use. Not considered part of the API and may break.
              -095     * @param message
              -096     */
              -097    @Deprecated
              -098    void sendMessageInternal(String message);
              -099}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.locales.MessageKey;
              +027import co.aikar.locales.MessageKeyProvider;
              +028import org.jetbrains.annotations.NotNull;
              +029
              +030import java.util.UUID;
              +031
              +032public interface CommandIssuer {
              +033    /**
              +034     * Gets the issuer in the platforms native object
              +035     * @param <T>
              +036     * @return
              +037     */
              +038    <T> T getIssuer();
              +039
              +040    CommandManager getManager();
              +041
              +042    /**
              +043     * Is this issue a player, or server/console sender
              +044     * @return
              +045     */
              +046    boolean isPlayer();
              +047
              +048    /**
              +049     * Send the Command Issuer a message
              +050     * @param message
              +051     */
              +052    default void sendMessage(String message) {
              +053        getManager().sendMessage(this, MessageType.INFO, MessageKeys.INFO_MESSAGE, "{message}", message);
              +054    }
              +055
              +056    /**
              +057     * @return the unique id of that issuer
              +058     */
              +059    @NotNull UUID getUniqueId();
              +060
              +061    /**
              +062     * Has permission node
              +063     * @param permission
              +064     * @return
              +065     */
              +066    boolean hasPermission(String permission);
              +067
              +068    default void sendError(MessageKeyProvider key, String... replacements) {
              +069        sendMessage(MessageType.ERROR, key.getMessageKey(), replacements);
              +070    }
              +071    default void sendSyntax(MessageKeyProvider key, String... replacements) {
              +072        sendMessage(MessageType.SYNTAX, key.getMessageKey(), replacements);
              +073    }
              +074    default void sendInfo(MessageKeyProvider key, String... replacements) {
              +075        sendMessage(MessageType.INFO, key.getMessageKey(), replacements);
              +076    }
              +077    default void sendError(MessageKey key, String... replacements) {
              +078        sendMessage(MessageType.ERROR, key, replacements);
              +079    }
              +080    default void sendSyntax(MessageKey key, String... replacements) {
              +081        sendMessage(MessageType.SYNTAX, key, replacements);
              +082    }
              +083    default void sendInfo(MessageKey key, String... replacements) {
              +084        sendMessage(MessageType.INFO, key, replacements);
              +085    }
              +086    default void sendMessage(MessageType type, MessageKeyProvider key, String... replacements) {
              +087        sendMessage(type, key.getMessageKey(), replacements);
              +088    }
              +089    default void sendMessage(MessageType type, MessageKey key, String... replacements) {
              +090        getManager().sendMessage(this, type, key, replacements);
              +091    }
              +092
              +093    /**
              +094     * @deprecated Do not call this, for internal use. Not considered part of the API and may break.
              +095     * @param message
              +096     */
              +097    @Deprecated
              +098    void sendMessageInternal(String message);
              +099}
               
               
               
              @@ -167,5 +168,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandManager.html b/docs/acf-core/src-html/co/aikar/commands/CommandManager.html index 414b474a..feac29be 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandManager.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandManager.html @@ -1,595 +1,596 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.annotation.Dependency;
              -027import co.aikar.locales.MessageKeyProvider;
              -028import co.aikar.util.Table;
              -029import org.jetbrains.annotations.NotNull;
              -030
              -031import java.lang.reflect.Field;
              -032import java.lang.reflect.InvocationTargetException;
              -033import java.lang.reflect.Method;
              -034import java.util.ArrayList;
              -035import java.util.Arrays;
              -036import java.util.Collection;
              -037import java.util.HashMap;
              -038import java.util.HashSet;
              -039import java.util.IdentityHashMap;
              -040import java.util.List;
              -041import java.util.Locale;
              -042import java.util.Map;
              -043import java.util.Objects;
              -044import java.util.Set;
              -045import java.util.Stack;
              -046import java.util.UUID;
              -047import java.util.concurrent.ConcurrentHashMap;
              -048
              -049
              -050@SuppressWarnings("WeakerAccess")
              -051public abstract class CommandManager<
              -052        IT,
              -053        I extends CommandIssuer,
              -054        FT,
              -055        MF extends MessageFormatter<FT>,
              -056        CEC extends CommandExecutionContext<CEC, I>,
              -057        CC extends ConditionContext<I>
              -058        > {
              -059
              -060    /**
              -061     * This is a stack incase a command calls a command
              -062     */
              -063    static ThreadLocal<Stack<CommandOperationContext>> commandOperationContext = ThreadLocal.withInitial(() -> new Stack<CommandOperationContext>() {
              -064        @Override
              -065        public synchronized CommandOperationContext peek() {
              -066            return super.size() == 0 ? null : super.peek();
              -067        }
              -068    });
              -069    protected Map<String, RootCommand> rootCommands = new HashMap<>();
              -070    protected final CommandReplacements replacements = new CommandReplacements(this);
              -071    protected final CommandConditions<I, CEC, CC> conditions = new CommandConditions<>(this);
              -072    protected ExceptionHandler defaultExceptionHandler = null;
              -073    boolean logUnhandledExceptions = true;
              -074    protected Table<Class<?>, String, Object> dependencies = new Table<>();
              -075    protected CommandHelpFormatter helpFormatter = new CommandHelpFormatter(this);
              -076
              -077    protected boolean usePerIssuerLocale = false;
              -078    protected List<IssuerLocaleChangedCallback<I>> localeChangedCallbacks = new ArrayList<>();
              -079    protected Set<Locale> supportedLanguages = new HashSet<>(Arrays.asList(Locales.ENGLISH, Locales.GERMAN, Locales.SPANISH, Locales.FRENCH, Locales.CZECH, Locales.PORTUGUESE, Locales.SWEDISH, Locales.NORWEGIAN_BOKMAAL, Locales.NORWEGIAN_NYNORSK, Locales.RUSSIAN, Locales.BULGARIAN, Locales.HUNGARIAN));
              -080    protected Map<MessageType, MF> formatters = new IdentityHashMap<>();
              -081    protected MF defaultFormatter;
              -082    protected int defaultHelpPerPage = 10;
              -083
              -084    protected Map<UUID, Locale> issuersLocale = new ConcurrentHashMap<>();
              -085
              -086    private Set<String> unstableAPIs = new HashSet<>();
              -087
              -088    private Annotations annotations = new Annotations<>(this);
              -089    private CommandRouter router = new CommandRouter(this);
              -090
              -091    public static CommandOperationContext getCurrentCommandOperationContext() {
              -092        return commandOperationContext.get().peek();
              -093    }
              -094
              -095    public static CommandIssuer getCurrentCommandIssuer() {
              -096        CommandOperationContext context = commandOperationContext.get().peek();
              -097        return context != null ? context.getCommandIssuer() : null;
              -098    }
              -099
              -100    public static CommandManager getCurrentCommandManager() {
              -101        CommandOperationContext context = commandOperationContext.get().peek();
              -102        return context != null ? context.getCommandManager() : null;
              -103    }
              -104
              -105    public MF setFormat(MessageType type, MF formatter) {
              -106        return formatters.put(type, formatter);
              -107    }
              -108
              -109    public MF getFormat(MessageType type) {
              -110        return formatters.getOrDefault(type, defaultFormatter);
              -111    }
              -112
              -113    public void setFormat(MessageType type, FT... colors) {
              -114        MF format = getFormat(type);
              -115        for (int i = 1; i <= colors.length; i++) {
              -116            format.setColor(i, colors[i - 1]);
              -117        }
              -118    }
              -119
              -120    public void setFormat(MessageType type, int i, FT color) {
              -121        MF format = getFormat(type);
              -122        format.setColor(i, color);
              -123    }
              -124
              -125    public MF getDefaultFormatter() {
              -126        return defaultFormatter;
              -127    }
              -128
              -129    public void setDefaultFormatter(MF defaultFormatter) {
              -130        this.defaultFormatter = defaultFormatter;
              -131    }
              -132
              -133    public CommandConditions<I, CEC, CC> getCommandConditions() {
              -134        return conditions;
              -135    }
              -136
              -137    /**
              -138     * Gets the command contexts manager
              -139     *
              -140     * @return Command Contexts
              -141     */
              -142    public abstract CommandContexts<?> getCommandContexts();
              -143
              -144    /**
              -145     * Gets the command completions manager
              -146     *
              -147     * @return Command Completions
              -148     */
              -149    public abstract CommandCompletions<?> getCommandCompletions();
              -150
              -151    /**
              -152     * @deprecated Unstable API
              -153     */
              -154    @Deprecated
              -155    @UnstableAPI
              -156    public CommandHelp generateCommandHelp(@NotNull String command) {
              -157        verifyUnstableAPI("help");
              -158        CommandOperationContext context = getCurrentCommandOperationContext();
              -159        if (context == null) {
              -160            throw new IllegalStateException("This method can only be called as part of a command execution.");
              -161        }
              -162        return generateCommandHelp(context.getCommandIssuer(), command);
              -163    }
              -164
              -165    /**
              -166     * @deprecated Unstable API
              -167     */
              -168    @Deprecated
              -169    @UnstableAPI
              -170    public CommandHelp generateCommandHelp(CommandIssuer issuer, @NotNull String command) {
              -171        verifyUnstableAPI("help");
              -172        return generateCommandHelp(issuer, obtainRootCommand(command));
              -173    }
              -174
              -175    /**
              -176     * @deprecated Unstable API
              -177     */
              -178    @Deprecated
              -179    @UnstableAPI
              -180    public CommandHelp generateCommandHelp() {
              -181        verifyUnstableAPI("help");
              -182        CommandOperationContext context = getCurrentCommandOperationContext();
              -183        if (context == null) {
              -184            throw new IllegalStateException("This method can only be called as part of a command execution.");
              -185        }
              -186        String commandLabel = context.getCommandLabel();
              -187        return generateCommandHelp(context.getCommandIssuer(), this.obtainRootCommand(commandLabel));
              -188    }
              -189
              -190    /**
              -191     * @deprecated Unstable API
              -192     */
              -193    @Deprecated
              -194    @UnstableAPI
              -195    public CommandHelp generateCommandHelp(CommandIssuer issuer, RootCommand rootCommand) {
              -196        verifyUnstableAPI("help");
              -197        return new CommandHelp(this, rootCommand, issuer);
              -198    }
              -199
              -200    /**
              -201     * @deprecated Unstable API
              -202     */
              -203    @Deprecated
              -204    @UnstableAPI
              -205    public int getDefaultHelpPerPage() {
              -206        verifyUnstableAPI("help");
              -207        return defaultHelpPerPage;
              -208    }
              -209
              -210    /**
              -211     * @deprecated Unstable API
              -212     */
              -213    @Deprecated
              -214    @UnstableAPI
              -215    public void setDefaultHelpPerPage(int defaultHelpPerPage) {
              -216        verifyUnstableAPI("help");
              -217        this.defaultHelpPerPage = defaultHelpPerPage;
              -218    }
              -219
              -220    /**
              -221     * @deprecated Unstable API
              -222     */
              -223    @Deprecated
              -224    @UnstableAPI
              -225    public void setHelpFormatter(CommandHelpFormatter helpFormatter) {
              -226        this.helpFormatter = helpFormatter;
              -227    }
              -228
              -229    /**
              -230     * @deprecated Unstable API
              -231     */
              -232    @Deprecated
              -233    @UnstableAPI
              -234    public CommandHelpFormatter getHelpFormatter() {
              -235        return helpFormatter;
              -236    }
              -237
              -238    CommandRouter getRouter() {
              -239        return router;
              -240    }
              -241
              -242    /**
              -243     * Registers a command with ACF
              -244     *
              -245     * @param command The command to register
              -246     * @return boolean
              -247     */
              -248    public abstract void registerCommand(BaseCommand command);
              -249
              -250    public abstract boolean hasRegisteredCommands();
              -251
              -252    public abstract boolean isCommandIssuer(Class<?> type);
              -253
              -254    // TODO: Change this to IT if we make a breaking change
              -255    public abstract I getCommandIssuer(Object issuer);
              -256
              -257    public abstract RootCommand createRootCommand(String cmd);
              -258
              -259    /**
              -260     * Returns a Locales Manager to add and modify language tables for your commands.
              -261     *
              -262     * @return
              -263     */
              -264    public abstract Locales getLocales();
              -265
              -266    public boolean usingPerIssuerLocale() {
              -267        return usePerIssuerLocale;
              -268    }
              -269
              -270    public boolean usePerIssuerLocale(boolean setting) {
              -271        boolean old = usePerIssuerLocale;
              -272        usePerIssuerLocale = setting;
              -273        return old;
              -274    }
              -275
              -276    public ConditionContext createConditionContext(CommandIssuer issuer, String config) {
              -277        //noinspection unchecked
              -278        return new ConditionContext(issuer, config);
              -279    }
              -280
              -281    public abstract CommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs);
              -282
              -283    public abstract CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args);
              -284
              -285    public abstract void log(final LogLevel level, final String message, final Throwable throwable);
              -286
              -287    public void log(final LogLevel level, final String message) {
              -288        log(level, message, null);
              -289    }
              -290
              -291    /**
              -292     * Lets you add custom string replacements that can be applied to annotation values,
              -293     * to reduce duplication/repetition of common values such as permission nodes and command prefixes.
              -294     * <p>
              -295     * Any replacement registered starts with a %
              -296     * <p>
              -297     * So for ex @CommandPermission("%staff")
              -298     *
              -299     * @return Replacements Manager
              -300     */
              -301    public CommandReplacements getCommandReplacements() {
              -302        return replacements;
              -303    }
              -304
              -305    public boolean hasPermission(CommandIssuer issuer, Set<String> permissions) {
              -306        for (String permission : permissions) {
              -307            if (!hasPermission(issuer, permission)) {
              -308                return false;
              -309            }
              -310        }
              -311        return true;
              -312    }
              -313
              -314    public boolean hasPermission(CommandIssuer issuer, String permission) {
              -315        if (permission == null || permission.isEmpty()) {
              -316            return true;
              -317        }
              -318        for (String perm : ACFPatterns.COMMA.split(permission)) {
              -319            if (!perm.isEmpty() && !issuer.hasPermission(perm)) {
              -320                return false;
              -321            }
              -322        }
              -323        return true;
              -324    }
              -325
              -326    public synchronized RootCommand getRootCommand(@NotNull String cmd) {
              -327        return rootCommands.get(ACFPatterns.SPACE.split(cmd.toLowerCase(), 2)[0]);
              -328    }
              -329
              -330    public synchronized RootCommand obtainRootCommand(@NotNull String cmd) {
              -331        return rootCommands.computeIfAbsent(ACFPatterns.SPACE.split(cmd.toLowerCase(), 2)[0], this::createRootCommand);
              -332    }
              -333
              -334    public abstract Collection<RootCommand> getRegisteredRootCommands();
              -335
              -336    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
              -337        return new RegisteredCommand(command, cmdName, method, prefSubCommand);
              -338    }
              -339
              -340    /**
              -341     * Sets the default {@link ExceptionHandler} that is called when an exception occurs while executing a command, if the command doesn't have it's own exception handler registered.
              -342     *
              -343     * @param exceptionHandler the handler that should handle uncaught exceptions.  May not be null if logExceptions is false
              -344     */
              -345    public void setDefaultExceptionHandler(ExceptionHandler exceptionHandler) {
              -346        if (exceptionHandler == null && !this.logUnhandledExceptions) {
              -347            throw new IllegalArgumentException("You may not disable the default exception handler and have logging of unhandled exceptions disabled");
              -348        }
              -349        defaultExceptionHandler = exceptionHandler;
              -350    }
              -351
              -352    /**
              -353     * Sets the default {@link ExceptionHandler} that is called when an exception occurs while executing a command, if the command doesn't have it's own exception handler registered, and lets you control if ACF should also log the exception still.
              -354     * <p>
              -355     * If you disable logging, you need to log it yourself in your handler.
              -356     *
              -357     * @param exceptionHandler the handler that should handle uncaught exceptions. May not be null if logExceptions is false
              -358     * @param logExceptions    Whether or not to log exceptions.
              -359     */
              -360    public void setDefaultExceptionHandler(ExceptionHandler exceptionHandler, boolean logExceptions) {
              -361        if (exceptionHandler == null && !logExceptions) {
              -362            throw new IllegalArgumentException("You may not disable the default exception handler and have logging of unhandled exceptions disabled");
              -363        }
              -364        this.logUnhandledExceptions = logExceptions;
              -365        this.defaultExceptionHandler = exceptionHandler;
              -366    }
              -367
              -368    public boolean isLoggingUnhandledExceptions() {
              -369        return this.logUnhandledExceptions;
              -370    }
              -371
              -372    /**
              -373     * Gets the current default exception handler, might be null.
              -374     *
              -375     * @return the default exception handler
              -376     */
              -377    public ExceptionHandler getDefaultExceptionHandler() {
              -378        return defaultExceptionHandler;
              -379    }
              -380
              -381    protected boolean handleUncaughtException(BaseCommand scope, RegisteredCommand registeredCommand, CommandIssuer sender, List<String> args, Throwable t) {
              -382        if (t instanceof InvocationTargetException && t.getCause() != null) {
              -383            t = t.getCause();
              -384        }
              -385        boolean result = false;
              -386        if (scope.getExceptionHandler() != null) {
              -387            result = scope.getExceptionHandler().execute(scope, registeredCommand, sender, args, t);
              -388        } else if (defaultExceptionHandler != null) {
              -389            result = defaultExceptionHandler.execute(scope, registeredCommand, sender, args, t);
              -390        }
              -391        return result;
              -392    }
              -393
              -394    public void sendMessage(IT issuerArg, MessageType type, MessageKeyProvider key, String... replacements) {
              -395        sendMessage(getCommandIssuer(issuerArg), type, key, replacements);
              -396    }
              -397
              -398    public void sendMessage(CommandIssuer issuer, MessageType type, MessageKeyProvider key, String... replacements) {
              -399        String message = formatMessage(issuer, type, key, replacements);
              -400
              -401        for (String msg : ACFPatterns.NEWLINE.split(message)) {
              -402            issuer.sendMessageInternal(ACFUtil.rtrim(msg));
              -403        }
              -404    }
              -405
              -406    public String formatMessage(CommandIssuer issuer, MessageType type, MessageKeyProvider key, String... replacements) {
              -407        String message = getLocales().getMessage(issuer, key.getMessageKey());
              -408        if (replacements.length > 0) {
              -409            message = ACFUtil.replaceStrings(message, replacements);
              -410        }
              -411
              -412        message = getCommandReplacements().replace(message);
              -413        message = getLocales().replaceI18NStrings(message);
              -414
              -415        MessageFormatter formatter = formatters.getOrDefault(type, defaultFormatter);
              -416        if (formatter != null) {
              -417            message = formatter.format(message);
              -418        }
              -419        return message;
              -420    }
              -421
              -422    public void onLocaleChange(IssuerLocaleChangedCallback<I> onChange) {
              -423        localeChangedCallbacks.add(onChange);
              -424    }
              -425
              -426    public void notifyLocaleChange(I issuer, Locale oldLocale, Locale newLocale) {
              -427        localeChangedCallbacks.forEach(cb -> {
              -428            try {
              -429                cb.onIssuerLocaleChange(issuer, oldLocale, newLocale);
              -430            } catch (Exception e) {
              -431                this.log(LogLevel.ERROR, "Error in notifyLocaleChange", e);
              -432            }
              -433        });
              -434    }
              -435
              -436    public Locale setIssuerLocale(IT issuer, Locale locale) {
              -437        I commandIssuer = getCommandIssuer(issuer);
              -438
              -439        Locale old = issuersLocale.put(commandIssuer.getUniqueId(), locale);
              -440        if (!Objects.equals(old, locale)) {
              -441            this.notifyLocaleChange(commandIssuer, old, locale);
              -442        }
              -443
              -444        return old;
              -445    }
              -446
              -447    public Locale getIssuerLocale(CommandIssuer issuer) {
              -448        if (usingPerIssuerLocale() && issuer != null) {
              -449            Locale locale = issuersLocale.get(issuer.getUniqueId());
              -450            if (locale != null) {
              -451                return locale;
              -452            }
              -453        }
              -454
              -455        return getLocales().getDefaultLocale();
              -456    }
              -457
              -458    CommandOperationContext<I> createCommandOperationContext(BaseCommand command, CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) {
              -459        //noinspection unchecked
              -460        return new CommandOperationContext<>(
              -461                this,
              -462                (I) issuer,
              -463                command,
              -464                commandLabel,
              -465                args,
              -466                isAsync
              -467        );
              -468    }
              -469
              -470    /**
              -471     * Gets a list of all currently supported languages for this manager.
              -472     * These locales will be automatically loaded from
              -473     *
              -474     * @return
              -475     */
              -476    public Set<Locale> getSupportedLanguages() {
              -477        return supportedLanguages;
              -478    }
              -479
              -480    /**
              -481     * Adds a new locale to the list of automatic Locales to load Message Bundles for.
              -482     * All bundles loaded under the previous supported languages will now automatically load for this new locale too.
              -483     *
              -484     * @param locale
              -485     */
              -486    public void addSupportedLanguage(Locale locale) {
              -487        supportedLanguages.add(locale);
              -488        getLocales().loadMissingBundles();
              -489    }
              -490
              -491    /**
              -492     * Registers an instance of a class to be registered as an injectable dependency.<br>
              -493     * The command manager will attempt to inject all fields in a command class that are annotated with
              -494     * {@link co.aikar.commands.annotation.Dependency} with the provided instance.
              -495     *
              -496     * @param clazz    the class the injector should look for when injecting
              -497     * @param instance the instance of the class that should be injected
              -498     * @throws IllegalStateException when there is already an instance for the provided class registered
              -499     */
              -500    public <T> void registerDependency(Class<? extends T> clazz, T instance) {
              -501        registerDependency(clazz, clazz.getName(), instance);
              -502    }
              -503
              -504    /**
              -505     * Registers an instance of a class to be registered as an injectable dependency.<br>
              -506     * The command manager will attempt to inject all fields in a command class that are annotated with
              -507     * {@link co.aikar.commands.annotation.Dependency} with the provided instance.
              -508     *
              -509     * @param clazz    the class the injector should look for when injecting
              -510     * @param key      the key which needs to be present if that
              -511     * @param instance the instance of the class that should be injected
              -512     * @throws IllegalStateException when there is already an instance for the provided class registered
              -513     */
              -514    public <T> void registerDependency(Class<? extends T> clazz, String key, T instance) {
              -515        if (dependencies.containsKey(clazz, key)) {
              -516            throw new IllegalStateException("There is already an instance of " + clazz.getName() + " with the key " + key + " registered!");
              -517        }
              -518
              -519        dependencies.put(clazz, key, instance);
              -520    }
              -521
              -522    /**
              -523     * Attempts to inject instances of classes registered with {@link CommandManager#registerDependency(Class, Object)}
              -524     * into all fields of the class and its superclasses that are marked with {@link Dependency}.
              -525     *
              -526     * @param baseCommand the instance which fields should be filled
              -527     */
              -528    void injectDependencies(BaseCommand baseCommand) {
              -529        Class clazz = baseCommand.getClass();
              -530        do {
              -531            for (Field field : clazz.getDeclaredFields()) {
              -532                if (annotations.hasAnnotation(field, Dependency.class)) {
              -533                    String dependency = annotations.getAnnotationValue(field, Dependency.class);
              -534                    String key = (key = dependency).isEmpty() ? field.getType().getName() : key;
              -535                    Object object = dependencies.row(field.getType()).get(key);
              -536                    if (object == null) {
              -537                        throw new UnresolvedDependencyException("Could not find a registered instance of " +
              -538                                field.getType().getName() + " with key " + key + " for field " + field.getName() +
              -539                                " in class " + baseCommand.getClass().getName());
              -540                    }
              -541
              -542                    try {
              -543                        boolean accessible = field.isAccessible();
              -544                        if (!accessible) {
              -545                            field.setAccessible(true);
              -546                        }
              -547                        field.set(baseCommand, object);
              -548                        field.setAccessible(accessible);
              -549                    } catch (IllegalAccessException e) {
              -550                        e.printStackTrace(); //TODO should we print our own exception here to make a more descriptive error?
              -551                    }
              -552                }
              -553            }
              -554            clazz = clazz.getSuperclass();
              -555        } while (!clazz.equals(BaseCommand.class));
              -556    }
              -557
              -558    /**
              -559     * @deprecated Use this with caution! If you enable and use Unstable API's, your next compile using ACF
              -560     * may require you to update your implementation to those unstable API's
              -561     */
              -562    @Deprecated
              -563    public void enableUnstableAPI(String api) {
              -564        unstableAPIs.add(api);
              -565    }
              -566
              -567    void verifyUnstableAPI(String api) {
              -568        if (!unstableAPIs.contains(api)) {
              -569            throw new IllegalStateException("Using an unstable API that has not been enabled ( " + api + "). See https://acfunstable.emc.gs");
              -570        }
              -571    }
              -572
              -573    boolean hasUnstableAPI(String api) {
              -574        return unstableAPIs.contains(api);
              -575    }
              -576
              -577    Annotations getAnnotations() {
              -578        return annotations;
              -579    }
              -580
              -581    public String getCommandPrefix(CommandIssuer issuer) {
              -582        return "";
              -583    }
              -584}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.annotation.Dependency;
              +027import co.aikar.locales.MessageKeyProvider;
              +028import co.aikar.util.Table;
              +029import org.jetbrains.annotations.NotNull;
              +030
              +031import java.lang.reflect.Field;
              +032import java.lang.reflect.InvocationTargetException;
              +033import java.lang.reflect.Method;
              +034import java.util.ArrayList;
              +035import java.util.Arrays;
              +036import java.util.Collection;
              +037import java.util.HashMap;
              +038import java.util.HashSet;
              +039import java.util.IdentityHashMap;
              +040import java.util.List;
              +041import java.util.Locale;
              +042import java.util.Map;
              +043import java.util.Objects;
              +044import java.util.Set;
              +045import java.util.Stack;
              +046import java.util.UUID;
              +047import java.util.concurrent.ConcurrentHashMap;
              +048
              +049
              +050@SuppressWarnings("WeakerAccess")
              +051public abstract class CommandManager<
              +052        IT,
              +053        I extends CommandIssuer,
              +054        FT,
              +055        MF extends MessageFormatter<FT>,
              +056        CEC extends CommandExecutionContext<CEC, I>,
              +057        CC extends ConditionContext<I>
              +058        > {
              +059
              +060    /**
              +061     * This is a stack incase a command calls a command
              +062     */
              +063    static ThreadLocal<Stack<CommandOperationContext>> commandOperationContext = ThreadLocal.withInitial(() -> new Stack<CommandOperationContext>() {
              +064        @Override
              +065        public synchronized CommandOperationContext peek() {
              +066            return super.size() == 0 ? null : super.peek();
              +067        }
              +068    });
              +069    protected Map<String, RootCommand> rootCommands = new HashMap<>();
              +070    protected final CommandReplacements replacements = new CommandReplacements(this);
              +071    protected final CommandConditions<I, CEC, CC> conditions = new CommandConditions<>(this);
              +072    protected ExceptionHandler defaultExceptionHandler = null;
              +073    boolean logUnhandledExceptions = true;
              +074    protected Table<Class<?>, String, Object> dependencies = new Table<>();
              +075    protected CommandHelpFormatter helpFormatter = new CommandHelpFormatter(this);
              +076
              +077    protected boolean usePerIssuerLocale = false;
              +078    protected List<IssuerLocaleChangedCallback<I>> localeChangedCallbacks = new ArrayList<>();
              +079    protected Set<Locale> supportedLanguages = new HashSet<>(Arrays.asList(Locales.ENGLISH, Locales.GERMAN, Locales.SPANISH, Locales.FRENCH, Locales.CZECH, Locales.PORTUGUESE, Locales.SWEDISH, Locales.NORWEGIAN_BOKMAAL, Locales.NORWEGIAN_NYNORSK, Locales.RUSSIAN, Locales.BULGARIAN, Locales.HUNGARIAN, Locales.TURKISH));
              +080    protected Map<MessageType, MF> formatters = new IdentityHashMap<>();
              +081    protected MF defaultFormatter;
              +082    protected int defaultHelpPerPage = 10;
              +083
              +084    protected Map<UUID, Locale> issuersLocale = new ConcurrentHashMap<>();
              +085
              +086    private Set<String> unstableAPIs = new HashSet<>();
              +087
              +088    private Annotations annotations = new Annotations<>(this);
              +089    private CommandRouter router = new CommandRouter(this);
              +090
              +091    public static CommandOperationContext getCurrentCommandOperationContext() {
              +092        return commandOperationContext.get().peek();
              +093    }
              +094
              +095    public static CommandIssuer getCurrentCommandIssuer() {
              +096        CommandOperationContext context = commandOperationContext.get().peek();
              +097        return context != null ? context.getCommandIssuer() : null;
              +098    }
              +099
              +100    public static CommandManager getCurrentCommandManager() {
              +101        CommandOperationContext context = commandOperationContext.get().peek();
              +102        return context != null ? context.getCommandManager() : null;
              +103    }
              +104
              +105    public MF setFormat(MessageType type, MF formatter) {
              +106        return formatters.put(type, formatter);
              +107    }
              +108
              +109    public MF getFormat(MessageType type) {
              +110        return formatters.getOrDefault(type, defaultFormatter);
              +111    }
              +112
              +113    public void setFormat(MessageType type, FT... colors) {
              +114        MF format = getFormat(type);
              +115        for (int i = 1; i <= colors.length; i++) {
              +116            format.setColor(i, colors[i - 1]);
              +117        }
              +118    }
              +119
              +120    public void setFormat(MessageType type, int i, FT color) {
              +121        MF format = getFormat(type);
              +122        format.setColor(i, color);
              +123    }
              +124
              +125    public MF getDefaultFormatter() {
              +126        return defaultFormatter;
              +127    }
              +128
              +129    public void setDefaultFormatter(MF defaultFormatter) {
              +130        this.defaultFormatter = defaultFormatter;
              +131    }
              +132
              +133    public CommandConditions<I, CEC, CC> getCommandConditions() {
              +134        return conditions;
              +135    }
              +136
              +137    /**
              +138     * Gets the command contexts manager
              +139     *
              +140     * @return Command Contexts
              +141     */
              +142    public abstract CommandContexts<?> getCommandContexts();
              +143
              +144    /**
              +145     * Gets the command completions manager
              +146     *
              +147     * @return Command Completions
              +148     */
              +149    public abstract CommandCompletions<?> getCommandCompletions();
              +150
              +151    /**
              +152     * @deprecated Unstable API
              +153     */
              +154    @Deprecated
              +155    @UnstableAPI
              +156    public CommandHelp generateCommandHelp(@NotNull String command) {
              +157        verifyUnstableAPI("help");
              +158        CommandOperationContext context = getCurrentCommandOperationContext();
              +159        if (context == null) {
              +160            throw new IllegalStateException("This method can only be called as part of a command execution.");
              +161        }
              +162        return generateCommandHelp(context.getCommandIssuer(), command);
              +163    }
              +164
              +165    /**
              +166     * @deprecated Unstable API
              +167     */
              +168    @Deprecated
              +169    @UnstableAPI
              +170    public CommandHelp generateCommandHelp(CommandIssuer issuer, @NotNull String command) {
              +171        verifyUnstableAPI("help");
              +172        return generateCommandHelp(issuer, obtainRootCommand(command));
              +173    }
              +174
              +175    /**
              +176     * @deprecated Unstable API
              +177     */
              +178    @Deprecated
              +179    @UnstableAPI
              +180    public CommandHelp generateCommandHelp() {
              +181        verifyUnstableAPI("help");
              +182        CommandOperationContext context = getCurrentCommandOperationContext();
              +183        if (context == null) {
              +184            throw new IllegalStateException("This method can only be called as part of a command execution.");
              +185        }
              +186        String commandLabel = context.getCommandLabel();
              +187        return generateCommandHelp(context.getCommandIssuer(), this.obtainRootCommand(commandLabel));
              +188    }
              +189
              +190    /**
              +191     * @deprecated Unstable API
              +192     */
              +193    @Deprecated
              +194    @UnstableAPI
              +195    public CommandHelp generateCommandHelp(CommandIssuer issuer, RootCommand rootCommand) {
              +196        verifyUnstableAPI("help");
              +197        return new CommandHelp(this, rootCommand, issuer);
              +198    }
              +199
              +200    /**
              +201     * @deprecated Unstable API
              +202     */
              +203    @Deprecated
              +204    @UnstableAPI
              +205    public int getDefaultHelpPerPage() {
              +206        verifyUnstableAPI("help");
              +207        return defaultHelpPerPage;
              +208    }
              +209
              +210    /**
              +211     * @deprecated Unstable API
              +212     */
              +213    @Deprecated
              +214    @UnstableAPI
              +215    public void setDefaultHelpPerPage(int defaultHelpPerPage) {
              +216        verifyUnstableAPI("help");
              +217        this.defaultHelpPerPage = defaultHelpPerPage;
              +218    }
              +219
              +220    /**
              +221     * @deprecated Unstable API
              +222     */
              +223    @Deprecated
              +224    @UnstableAPI
              +225    public void setHelpFormatter(CommandHelpFormatter helpFormatter) {
              +226        this.helpFormatter = helpFormatter;
              +227    }
              +228
              +229    /**
              +230     * @deprecated Unstable API
              +231     */
              +232    @Deprecated
              +233    @UnstableAPI
              +234    public CommandHelpFormatter getHelpFormatter() {
              +235        return helpFormatter;
              +236    }
              +237
              +238    CommandRouter getRouter() {
              +239        return router;
              +240    }
              +241
              +242    /**
              +243     * Registers a command with ACF
              +244     *
              +245     * @param command The command to register
              +246     * @return boolean
              +247     */
              +248    public abstract void registerCommand(BaseCommand command);
              +249
              +250    public abstract boolean hasRegisteredCommands();
              +251
              +252    public abstract boolean isCommandIssuer(Class<?> type);
              +253
              +254    // TODO: Change this to IT if we make a breaking change
              +255    public abstract I getCommandIssuer(Object issuer);
              +256
              +257    public abstract RootCommand createRootCommand(String cmd);
              +258
              +259    /**
              +260     * Returns a Locales Manager to add and modify language tables for your commands.
              +261     *
              +262     * @return
              +263     */
              +264    public abstract Locales getLocales();
              +265
              +266    public boolean usingPerIssuerLocale() {
              +267        return usePerIssuerLocale;
              +268    }
              +269
              +270    public boolean usePerIssuerLocale(boolean setting) {
              +271        boolean old = usePerIssuerLocale;
              +272        usePerIssuerLocale = setting;
              +273        return old;
              +274    }
              +275
              +276    public ConditionContext createConditionContext(CommandIssuer issuer, String config) {
              +277        //noinspection unchecked
              +278        return new ConditionContext(issuer, config);
              +279    }
              +280
              +281    public abstract CommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs);
              +282
              +283    public abstract CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args);
              +284
              +285    public abstract void log(final LogLevel level, final String message, final Throwable throwable);
              +286
              +287    public void log(final LogLevel level, final String message) {
              +288        log(level, message, null);
              +289    }
              +290
              +291    /**
              +292     * Lets you add custom string replacements that can be applied to annotation values,
              +293     * to reduce duplication/repetition of common values such as permission nodes and command prefixes.
              +294     * <p>
              +295     * Any replacement registered starts with a %
              +296     * <p>
              +297     * So for ex @CommandPermission("%staff")
              +298     *
              +299     * @return Replacements Manager
              +300     */
              +301    public CommandReplacements getCommandReplacements() {
              +302        return replacements;
              +303    }
              +304
              +305    public boolean hasPermission(CommandIssuer issuer, Set<String> permissions) {
              +306        for (String permission : permissions) {
              +307            if (!hasPermission(issuer, permission)) {
              +308                return false;
              +309            }
              +310        }
              +311        return true;
              +312    }
              +313
              +314    public boolean hasPermission(CommandIssuer issuer, String permission) {
              +315        if (permission == null || permission.isEmpty()) {
              +316            return true;
              +317        }
              +318        for (String perm : ACFPatterns.COMMA.split(permission)) {
              +319            if (!perm.isEmpty() && !issuer.hasPermission(perm)) {
              +320                return false;
              +321            }
              +322        }
              +323        return true;
              +324    }
              +325
              +326    public synchronized RootCommand getRootCommand(@NotNull String cmd) {
              +327        return rootCommands.get(ACFPatterns.SPACE.split(cmd.toLowerCase(Locale.ENGLISH), 2)[0]);
              +328    }
              +329
              +330    public synchronized RootCommand obtainRootCommand(@NotNull String cmd) {
              +331        return rootCommands.computeIfAbsent(ACFPatterns.SPACE.split(cmd.toLowerCase(Locale.ENGLISH), 2)[0], this::createRootCommand);
              +332    }
              +333
              +334    public abstract Collection<RootCommand> getRegisteredRootCommands();
              +335
              +336    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
              +337        return new RegisteredCommand(command, cmdName, method, prefSubCommand);
              +338    }
              +339
              +340    /**
              +341     * Sets the default {@link ExceptionHandler} that is called when an exception occurs while executing a command, if the command doesn't have it's own exception handler registered.
              +342     *
              +343     * @param exceptionHandler the handler that should handle uncaught exceptions.  May not be null if logExceptions is false
              +344     */
              +345    public void setDefaultExceptionHandler(ExceptionHandler exceptionHandler) {
              +346        if (exceptionHandler == null && !this.logUnhandledExceptions) {
              +347            throw new IllegalArgumentException("You may not disable the default exception handler and have logging of unhandled exceptions disabled");
              +348        }
              +349        defaultExceptionHandler = exceptionHandler;
              +350    }
              +351
              +352    /**
              +353     * Sets the default {@link ExceptionHandler} that is called when an exception occurs while executing a command, if the command doesn't have it's own exception handler registered, and lets you control if ACF should also log the exception still.
              +354     * <p>
              +355     * If you disable logging, you need to log it yourself in your handler.
              +356     *
              +357     * @param exceptionHandler the handler that should handle uncaught exceptions. May not be null if logExceptions is false
              +358     * @param logExceptions    Whether or not to log exceptions.
              +359     */
              +360    public void setDefaultExceptionHandler(ExceptionHandler exceptionHandler, boolean logExceptions) {
              +361        if (exceptionHandler == null && !logExceptions) {
              +362            throw new IllegalArgumentException("You may not disable the default exception handler and have logging of unhandled exceptions disabled");
              +363        }
              +364        this.logUnhandledExceptions = logExceptions;
              +365        this.defaultExceptionHandler = exceptionHandler;
              +366    }
              +367
              +368    public boolean isLoggingUnhandledExceptions() {
              +369        return this.logUnhandledExceptions;
              +370    }
              +371
              +372    /**
              +373     * Gets the current default exception handler, might be null.
              +374     *
              +375     * @return the default exception handler
              +376     */
              +377    public ExceptionHandler getDefaultExceptionHandler() {
              +378        return defaultExceptionHandler;
              +379    }
              +380
              +381    protected boolean handleUncaughtException(BaseCommand scope, RegisteredCommand registeredCommand, CommandIssuer sender, List<String> args, Throwable t) {
              +382        if (t instanceof InvocationTargetException && t.getCause() != null) {
              +383            t = t.getCause();
              +384        }
              +385        boolean result = false;
              +386        if (scope.getExceptionHandler() != null) {
              +387            result = scope.getExceptionHandler().execute(scope, registeredCommand, sender, args, t);
              +388        } else if (defaultExceptionHandler != null) {
              +389            result = defaultExceptionHandler.execute(scope, registeredCommand, sender, args, t);
              +390        }
              +391        return result;
              +392    }
              +393
              +394    public void sendMessage(IT issuerArg, MessageType type, MessageKeyProvider key, String... replacements) {
              +395        sendMessage(getCommandIssuer(issuerArg), type, key, replacements);
              +396    }
              +397
              +398    public void sendMessage(CommandIssuer issuer, MessageType type, MessageKeyProvider key, String... replacements) {
              +399        String message = formatMessage(issuer, type, key, replacements);
              +400
              +401        for (String msg : ACFPatterns.NEWLINE.split(message)) {
              +402            issuer.sendMessageInternal(ACFUtil.rtrim(msg));
              +403        }
              +404    }
              +405
              +406    public String formatMessage(CommandIssuer issuer, MessageType type, MessageKeyProvider key, String... replacements) {
              +407        String message = getLocales().getMessage(issuer, key.getMessageKey());
              +408        if (replacements.length > 0) {
              +409            message = ACFUtil.replaceStrings(message, replacements);
              +410        }
              +411
              +412        message = getCommandReplacements().replace(message);
              +413        message = getLocales().replaceI18NStrings(message);
              +414
              +415        MessageFormatter formatter = formatters.getOrDefault(type, defaultFormatter);
              +416        if (formatter != null) {
              +417            message = formatter.format(message);
              +418        }
              +419        return message;
              +420    }
              +421
              +422    public void onLocaleChange(IssuerLocaleChangedCallback<I> onChange) {
              +423        localeChangedCallbacks.add(onChange);
              +424    }
              +425
              +426    public void notifyLocaleChange(I issuer, Locale oldLocale, Locale newLocale) {
              +427        localeChangedCallbacks.forEach(cb -> {
              +428            try {
              +429                cb.onIssuerLocaleChange(issuer, oldLocale, newLocale);
              +430            } catch (Exception e) {
              +431                this.log(LogLevel.ERROR, "Error in notifyLocaleChange", e);
              +432            }
              +433        });
              +434    }
              +435
              +436    public Locale setIssuerLocale(IT issuer, Locale locale) {
              +437        I commandIssuer = getCommandIssuer(issuer);
              +438
              +439        Locale old = issuersLocale.put(commandIssuer.getUniqueId(), locale);
              +440        if (!Objects.equals(old, locale)) {
              +441            this.notifyLocaleChange(commandIssuer, old, locale);
              +442        }
              +443
              +444        return old;
              +445    }
              +446
              +447    public Locale getIssuerLocale(CommandIssuer issuer) {
              +448        if (usingPerIssuerLocale() && issuer != null) {
              +449            Locale locale = issuersLocale.get(issuer.getUniqueId());
              +450            if (locale != null) {
              +451                return locale;
              +452            }
              +453        }
              +454
              +455        return getLocales().getDefaultLocale();
              +456    }
              +457
              +458    CommandOperationContext<I> createCommandOperationContext(BaseCommand command, CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) {
              +459        //noinspection unchecked
              +460        return new CommandOperationContext<>(
              +461                this,
              +462                (I) issuer,
              +463                command,
              +464                commandLabel,
              +465                args,
              +466                isAsync
              +467        );
              +468    }
              +469
              +470    /**
              +471     * Gets a list of all currently supported languages for this manager.
              +472     * These locales will be automatically loaded from
              +473     *
              +474     * @return
              +475     */
              +476    public Set<Locale> getSupportedLanguages() {
              +477        return supportedLanguages;
              +478    }
              +479
              +480    /**
              +481     * Adds a new locale to the list of automatic Locales to load Message Bundles for.
              +482     * All bundles loaded under the previous supported languages will now automatically load for this new locale too.
              +483     *
              +484     * @param locale
              +485     */
              +486    public void addSupportedLanguage(Locale locale) {
              +487        supportedLanguages.add(locale);
              +488        getLocales().loadMissingBundles();
              +489    }
              +490
              +491    /**
              +492     * Registers an instance of a class to be registered as an injectable dependency.<br>
              +493     * The command manager will attempt to inject all fields in a command class that are annotated with
              +494     * {@link co.aikar.commands.annotation.Dependency} with the provided instance.
              +495     *
              +496     * @param clazz    the class the injector should look for when injecting
              +497     * @param instance the instance of the class that should be injected
              +498     * @throws IllegalStateException when there is already an instance for the provided class registered
              +499     */
              +500    public <T> void registerDependency(Class<? extends T> clazz, T instance) {
              +501        registerDependency(clazz, clazz.getName(), instance);
              +502    }
              +503
              +504    /**
              +505     * Registers an instance of a class to be registered as an injectable dependency.<br>
              +506     * The command manager will attempt to inject all fields in a command class that are annotated with
              +507     * {@link co.aikar.commands.annotation.Dependency} with the provided instance.
              +508     *
              +509     * @param clazz    the class the injector should look for when injecting
              +510     * @param key      the key which needs to be present if that
              +511     * @param instance the instance of the class that should be injected
              +512     * @throws IllegalStateException when there is already an instance for the provided class registered
              +513     */
              +514    public <T> void registerDependency(Class<? extends T> clazz, String key, T instance) {
              +515        if (dependencies.containsKey(clazz, key)) {
              +516            throw new IllegalStateException("There is already an instance of " + clazz.getName() + " with the key " + key + " registered!");
              +517        }
              +518
              +519        dependencies.put(clazz, key, instance);
              +520    }
              +521
              +522    /**
              +523     * Attempts to inject instances of classes registered with {@link CommandManager#registerDependency(Class, Object)}
              +524     * into all fields of the class and its superclasses that are marked with {@link Dependency}.
              +525     *
              +526     * @param baseCommand the instance which fields should be filled
              +527     */
              +528    void injectDependencies(BaseCommand baseCommand) {
              +529        Class clazz = baseCommand.getClass();
              +530        do {
              +531            for (Field field : clazz.getDeclaredFields()) {
              +532                if (annotations.hasAnnotation(field, Dependency.class)) {
              +533                    String dependency = annotations.getAnnotationValue(field, Dependency.class);
              +534                    String key = (key = dependency).isEmpty() ? field.getType().getName() : key;
              +535                    Object object = dependencies.row(field.getType()).get(key);
              +536                    if (object == null) {
              +537                        throw new UnresolvedDependencyException("Could not find a registered instance of " +
              +538                                field.getType().getName() + " with key " + key + " for field " + field.getName() +
              +539                                " in class " + baseCommand.getClass().getName());
              +540                    }
              +541
              +542                    try {
              +543                        boolean accessible = field.isAccessible();
              +544                        if (!accessible) {
              +545                            field.setAccessible(true);
              +546                        }
              +547                        field.set(baseCommand, object);
              +548                        field.setAccessible(accessible);
              +549                    } catch (IllegalAccessException e) {
              +550                        e.printStackTrace(); //TODO should we print our own exception here to make a more descriptive error?
              +551                    }
              +552                }
              +553            }
              +554            clazz = clazz.getSuperclass();
              +555        } while (!clazz.equals(BaseCommand.class));
              +556    }
              +557
              +558    /**
              +559     * @deprecated Use this with caution! If you enable and use Unstable API's, your next compile using ACF
              +560     * may require you to update your implementation to those unstable API's
              +561     */
              +562    @Deprecated
              +563    public void enableUnstableAPI(String api) {
              +564        unstableAPIs.add(api);
              +565    }
              +566
              +567    void verifyUnstableAPI(String api) {
              +568        if (!unstableAPIs.contains(api)) {
              +569            throw new IllegalStateException("Using an unstable API that has not been enabled ( " + api + "). See https://acfunstable.emc.gs");
              +570        }
              +571    }
              +572
              +573    boolean hasUnstableAPI(String api) {
              +574        return unstableAPIs.contains(api);
              +575    }
              +576
              +577    Annotations getAnnotations() {
              +578        return annotations;
              +579    }
              +580
              +581    public String getCommandPrefix(CommandIssuer issuer) {
              +582        return "";
              +583    }
              +584}
               
               
               
              @@ -652,5 +653,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandOperationContext.html b/docs/acf-core/src-html/co/aikar/commands/CommandOperationContext.html index 3440a71d..b2a235a3 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandOperationContext.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandOperationContext.html @@ -1,117 +1,118 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import java.lang.annotation.Annotation;
              -027import java.util.List;
              -028
              -029/**
              -030 * Holds information about the currently executing command on this thread
              -031 */
              -032public class CommandOperationContext<I extends CommandIssuer> {
              -033
              -034    private final CommandManager manager;
              -035    private final I issuer;
              -036    private final BaseCommand command;
              -037    private final String commandLabel;
              -038    private final String[] args;
              -039    private final boolean isAsync;
              -040    private RegisteredCommand registeredCommand;
              -041    List<String> enumCompletionValues;
              -042
              -043    CommandOperationContext(CommandManager manager, I issuer, BaseCommand command, String commandLabel, String[] args, boolean isAsync) {
              -044        this.manager = manager;
              -045        this.issuer = issuer;
              -046        this.command = command;
              -047        this.commandLabel = commandLabel;
              -048        this.args = args;
              -049        this.isAsync = isAsync;
              -050    }
              -051
              -052    public CommandManager getCommandManager() {
              -053        return manager;
              -054    }
              -055
              -056    public I getCommandIssuer() {
              -057        return issuer;
              -058    }
              -059
              -060    public BaseCommand getCommand() {
              -061        return command;
              -062    }
              -063
              -064    public String getCommandLabel() {
              -065        return commandLabel;
              -066    }
              -067
              -068    public String[] getArgs() {
              -069        return args;
              -070    }
              -071
              -072    public boolean isAsync() {
              -073        return isAsync;
              -074    }
              -075
              -076    public void setRegisteredCommand(RegisteredCommand registeredCommand) {
              -077        this.registeredCommand = registeredCommand;
              -078    }
              -079
              -080    public RegisteredCommand getRegisteredCommand() {
              -081        return registeredCommand;
              -082    }
              -083
              -084    /**
              -085     * This method will not support annotation processors!! use getAnnotationValue or hasAnnotation
              -086     *
              -087     * @deprecated Use {@link #getAnnotationValue(Class)}
              -088     */
              -089    @Deprecated
              -090    public <T extends Annotation> T getAnnotation(Class<T> anno) {
              -091        return registeredCommand.method.getAnnotation(anno);
              -092    }
              -093
              -094    public <T extends Annotation> String getAnnotationValue(Class<T> cls) {
              -095        return manager.getAnnotations().getAnnotationValue(registeredCommand.method, cls);
              -096    }
              -097
              -098    public <T extends Annotation> String getAnnotationValue(Class<T> cls, int options) {
              -099        return manager.getAnnotations().getAnnotationValue(registeredCommand.method, cls, options);
              -100    }
              -101
              -102    public boolean hasAnnotation(Class<? extends Annotation> anno) {
              -103        return getAnnotation(anno) != null;
              -104    }
              -105
              -106}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import java.lang.annotation.Annotation;
              +027import java.util.List;
              +028
              +029/**
              +030 * Holds information about the currently executing command on this thread
              +031 */
              +032public class CommandOperationContext<I extends CommandIssuer> {
              +033
              +034    private final CommandManager manager;
              +035    private final I issuer;
              +036    private final BaseCommand command;
              +037    private final String commandLabel;
              +038    private final String[] args;
              +039    private final boolean isAsync;
              +040    private RegisteredCommand registeredCommand;
              +041    List<String> enumCompletionValues;
              +042
              +043    CommandOperationContext(CommandManager manager, I issuer, BaseCommand command, String commandLabel, String[] args, boolean isAsync) {
              +044        this.manager = manager;
              +045        this.issuer = issuer;
              +046        this.command = command;
              +047        this.commandLabel = commandLabel;
              +048        this.args = args;
              +049        this.isAsync = isAsync;
              +050    }
              +051
              +052    public CommandManager getCommandManager() {
              +053        return manager;
              +054    }
              +055
              +056    public I getCommandIssuer() {
              +057        return issuer;
              +058    }
              +059
              +060    public BaseCommand getCommand() {
              +061        return command;
              +062    }
              +063
              +064    public String getCommandLabel() {
              +065        return commandLabel;
              +066    }
              +067
              +068    public String[] getArgs() {
              +069        return args;
              +070    }
              +071
              +072    public boolean isAsync() {
              +073        return isAsync;
              +074    }
              +075
              +076    public void setRegisteredCommand(RegisteredCommand registeredCommand) {
              +077        this.registeredCommand = registeredCommand;
              +078    }
              +079
              +080    public RegisteredCommand getRegisteredCommand() {
              +081        return registeredCommand;
              +082    }
              +083
              +084    /**
              +085     * This method will not support annotation processors!! use getAnnotationValue or hasAnnotation
              +086     *
              +087     * @deprecated Use {@link #getAnnotationValue(Class)}
              +088     */
              +089    @Deprecated
              +090    public <T extends Annotation> T getAnnotation(Class<T> anno) {
              +091        return registeredCommand.method.getAnnotation(anno);
              +092    }
              +093
              +094    public <T extends Annotation> String getAnnotationValue(Class<T> cls) {
              +095        return manager.getAnnotations().getAnnotationValue(registeredCommand.method, cls);
              +096    }
              +097
              +098    public <T extends Annotation> String getAnnotationValue(Class<T> cls, int options) {
              +099        return manager.getAnnotations().getAnnotationValue(registeredCommand.method, cls, options);
              +100    }
              +101
              +102    public boolean hasAnnotation(Class<? extends Annotation> anno) {
              +103        return getAnnotation(anno) != null;
              +104    }
              +105
              +106}
               
               
               
              @@ -174,5 +175,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandParameter.html b/docs/acf-core/src-html/co/aikar/commands/CommandParameter.html index 795614ab..4fbb0d09 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandParameter.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandParameter.html @@ -1,289 +1,290 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.annotation.CommandPermission;
              -027import co.aikar.commands.annotation.Conditions;
              -028import co.aikar.commands.annotation.Default;
              -029import co.aikar.commands.annotation.Description;
              -030import co.aikar.commands.annotation.Flags;
              -031import co.aikar.commands.annotation.Optional;
              -032import co.aikar.commands.annotation.Single;
              -033import co.aikar.commands.annotation.Syntax;
              -034import co.aikar.commands.annotation.Values;
              -035import co.aikar.commands.contexts.ContextResolver;
              -036import co.aikar.commands.contexts.IssuerAwareContextResolver;
              -037import co.aikar.commands.contexts.IssuerOnlyContextResolver;
              -038import co.aikar.commands.contexts.OptionalContextResolver;
              -039
              -040import java.lang.reflect.Parameter;
              -041import java.util.Arrays;
              -042import java.util.HashMap;
              -043import java.util.HashSet;
              -044import java.util.Map;
              -045import java.util.Set;
              -046
              -047public class CommandParameter<CEC extends CommandExecutionContext<CEC, ? extends CommandIssuer>> {
              -048    private final Parameter parameter;
              -049    private final Class<?> type;
              -050    private final String name;
              -051    private final CommandManager manager;
              -052    private final int paramIndex;
              -053
              -054    private ContextResolver<?, CEC> resolver;
              -055    private boolean optional;
              -056    private Set<String> permissions = new HashSet<>();
              -057    private String permission;
              -058    private String description;
              -059    private String defaultValue;
              -060    private String syntax;
              -061    private String conditions;
              -062    private boolean requiresInput;
              -063    private boolean commandIssuer;
              -064    private String[] values;
              -065    private Map<String, String> flags;
              -066    private boolean canConsumeInput;
              -067    private boolean optionalResolver;
              -068    boolean consumesRest;
              -069
              -070    public CommandParameter(RegisteredCommand<CEC> command, Parameter param, int paramIndex, boolean isLast) {
              -071        this.parameter = param;
              -072        this.type = param.getType();
              -073        this.name = param.getName(); // do we care for an annotation to supply name?
              -074        this.manager = command.manager;
              -075        this.paramIndex = paramIndex;
              -076        Annotations annotations = manager.getAnnotations();
              -077
              -078        this.defaultValue = annotations.getAnnotationValue(param, Default.class, Annotations.REPLACEMENTS | (type != String.class ? Annotations.NO_EMPTY : 0));
              -079        this.description = annotations.getAnnotationValue(param, Description.class, Annotations.REPLACEMENTS | Annotations.DEFAULT_EMPTY);
              -080        this.conditions = annotations.getAnnotationValue(param, Conditions.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              -081
              -082        //noinspection unchecked
              -083        this.resolver = manager.getCommandContexts().getResolver(type);
              -084        if (this.resolver == null) {
              -085            ACFUtil.sneaky(new InvalidCommandContextException(
              -086                    "Parameter " + type.getSimpleName() + " of " + command + " has no applicable context resolver"
              -087            ));
              -088        }
              -089
              -090        this.optional = annotations.hasAnnotation(param, Optional.class) || this.defaultValue != null || (isLast && type == String[].class);
              -091        this.permission = annotations.getAnnotationValue(param, CommandPermission.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              -092        this.optionalResolver = isOptionalResolver(resolver);
              -093        this.requiresInput = !this.optional && !this.optionalResolver;
              -094        //noinspection unchecked
              -095        this.commandIssuer = paramIndex == 0 && manager.isCommandIssuer(type);
              -096        this.canConsumeInput = !this.commandIssuer && !(resolver instanceof IssuerOnlyContextResolver);
              -097        this.consumesRest = (type == String.class && !annotations.hasAnnotation(param, Single.class)) || (isLast && type == String[].class);
              -098
              -099        this.values = annotations.getAnnotationValues(param, Values.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              -100
              -101        this.syntax = null;
              -102        if (!commandIssuer) {
              -103            this.syntax = annotations.getAnnotationValue(param, Syntax.class);
              -104            if (syntax == null) {
              -105                if (!requiresInput && canConsumeInput) {
              -106                    this.syntax = "[" + name + "]";
              -107                } else if (requiresInput) {
              -108                    this.syntax = "<" + name + ">";
              -109                }
              -110            }
              -111        }
              -112
              -113        this.flags = new HashMap<>();
              -114        String flags = annotations.getAnnotationValue(param, Flags.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              -115        if (flags != null) {
              -116            parseFlags(flags);
              -117        }
              -118        inheritContextFlags(command.scope);
              -119        this.computePermissions();
              -120    }
              -121
              -122    private void inheritContextFlags(BaseCommand scope) {
              -123        if (!scope.contextFlags.isEmpty()) {
              -124            Class<?> pCls = this.type;
              -125            do {
              -126                parseFlags(scope.contextFlags.get(pCls));
              -127            } while ((pCls = pCls.getSuperclass()) != null);
              -128        }
              -129        if (scope.parentCommand != null) {
              -130            inheritContextFlags(scope.parentCommand);
              -131        }
              -132    }
              -133
              -134    private void parseFlags(String flags) {
              -135        if (flags != null) {
              -136            for (String s : ACFPatterns.COMMA.split(manager.getCommandReplacements().replace(flags))) {
              -137                String[] v = ACFPatterns.EQUALS.split(s, 2);
              -138                if (!this.flags.containsKey(v[0])) {
              -139                    this.flags.put(v[0], v.length > 1 ? v[1] : null);
              -140                }
              -141            }
              -142        }
              -143    }
              -144
              -145    private void computePermissions() {
              -146        this.permissions.clear();
              -147        if (this.permission != null && !this.permission.isEmpty()) {
              -148            this.permissions.addAll(Arrays.asList(ACFPatterns.COMMA.split(this.permission)));
              -149        }
              -150    }
              -151
              -152    private boolean isOptionalResolver(ContextResolver<?, CEC> resolver) {
              -153        return resolver instanceof IssuerAwareContextResolver
              -154                || resolver instanceof IssuerOnlyContextResolver
              -155                || resolver instanceof OptionalContextResolver;
              -156    }
              -157
              -158
              -159    public Parameter getParameter() {
              -160        return parameter;
              -161    }
              -162
              -163    public Class<?> getType() {
              -164        return type;
              -165    }
              -166
              -167    public String getName() {
              -168        return name;
              -169    }
              -170
              -171    public CommandManager getManager() {
              -172        return manager;
              -173    }
              -174
              -175    public int getParamIndex() {
              -176        return paramIndex;
              -177    }
              -178
              -179    public ContextResolver<?, CEC> getResolver() {
              -180        return resolver;
              -181    }
              -182
              -183    public void setResolver(ContextResolver<?, CEC> resolver) {
              -184        this.resolver = resolver;
              -185    }
              -186
              -187    public boolean isOptional() {
              -188        return optional;
              -189    }
              -190
              -191    public void setOptional(boolean optional) {
              -192        this.optional = optional;
              -193    }
              -194
              -195    public String getDescription() {
              -196        return description;
              -197    }
              -198
              -199    public void setDescription(String description) {
              -200        this.description = description;
              -201    }
              -202
              -203    public String getDefaultValue() {
              -204        return defaultValue;
              -205    }
              -206
              -207    public void setDefaultValue(String defaultValue) {
              -208        this.defaultValue = defaultValue;
              -209    }
              -210
              -211    public boolean isCommandIssuer() {
              -212        return commandIssuer;
              -213    }
              -214
              -215    public void setCommandIssuer(boolean commandIssuer) {
              -216        this.commandIssuer = commandIssuer;
              -217    }
              -218
              -219    public String[] getValues() {
              -220        return values;
              -221    }
              -222
              -223    public void setValues(String[] values) {
              -224        this.values = values;
              -225    }
              -226
              -227    public Map<String, String> getFlags() {
              -228        return flags;
              -229    }
              -230
              -231    public void setFlags(Map<String, String> flags) {
              -232        this.flags = flags;
              -233    }
              -234
              -235    public boolean canConsumeInput() {
              -236        return canConsumeInput;
              -237    }
              -238
              -239    public void setCanConsumeInput(boolean canConsumeInput) {
              -240        this.canConsumeInput = canConsumeInput;
              -241    }
              -242
              -243    public void setOptionalResolver(boolean optionalResolver) {
              -244        this.optionalResolver = optionalResolver;
              -245    }
              -246
              -247    public boolean isOptionalResolver() {
              -248        return optionalResolver;
              -249    }
              -250
              -251    public boolean requiresInput() {
              -252        return requiresInput;
              -253    }
              -254
              -255    public void setRequiresInput(boolean requiresInput) {
              -256        this.requiresInput = requiresInput;
              -257    }
              -258
              -259    public String getSyntax() {
              -260        return syntax;
              -261    }
              -262
              -263    public void setSyntax(String syntax) {
              -264        this.syntax = syntax;
              -265    }
              -266
              -267    public String getConditions() {
              -268        return conditions;
              -269    }
              -270
              -271    public void setConditions(String conditions) {
              -272        this.conditions = conditions;
              -273    }
              -274
              -275    public Set<String> getRequiredPermissions() {
              -276        return permissions;
              -277    }
              -278}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.annotation.CommandPermission;
              +027import co.aikar.commands.annotation.Conditions;
              +028import co.aikar.commands.annotation.Default;
              +029import co.aikar.commands.annotation.Description;
              +030import co.aikar.commands.annotation.Flags;
              +031import co.aikar.commands.annotation.Optional;
              +032import co.aikar.commands.annotation.Single;
              +033import co.aikar.commands.annotation.Syntax;
              +034import co.aikar.commands.annotation.Values;
              +035import co.aikar.commands.contexts.ContextResolver;
              +036import co.aikar.commands.contexts.IssuerAwareContextResolver;
              +037import co.aikar.commands.contexts.IssuerOnlyContextResolver;
              +038import co.aikar.commands.contexts.OptionalContextResolver;
              +039
              +040import java.lang.reflect.Parameter;
              +041import java.util.Arrays;
              +042import java.util.HashMap;
              +043import java.util.HashSet;
              +044import java.util.Map;
              +045import java.util.Set;
              +046
              +047public class CommandParameter<CEC extends CommandExecutionContext<CEC, ? extends CommandIssuer>> {
              +048    private final Parameter parameter;
              +049    private final Class<?> type;
              +050    private final String name;
              +051    private final CommandManager manager;
              +052    private final int paramIndex;
              +053
              +054    private ContextResolver<?, CEC> resolver;
              +055    private boolean optional;
              +056    private Set<String> permissions = new HashSet<>();
              +057    private String permission;
              +058    private String description;
              +059    private String defaultValue;
              +060    private String syntax;
              +061    private String conditions;
              +062    private boolean requiresInput;
              +063    private boolean commandIssuer;
              +064    private String[] values;
              +065    private Map<String, String> flags;
              +066    private boolean canConsumeInput;
              +067    private boolean optionalResolver;
              +068    boolean consumesRest;
              +069
              +070    public CommandParameter(RegisteredCommand<CEC> command, Parameter param, int paramIndex, boolean isLast) {
              +071        this.parameter = param;
              +072        this.type = param.getType();
              +073        this.name = param.getName(); // do we care for an annotation to supply name?
              +074        this.manager = command.manager;
              +075        this.paramIndex = paramIndex;
              +076        Annotations annotations = manager.getAnnotations();
              +077
              +078        this.defaultValue = annotations.getAnnotationValue(param, Default.class, Annotations.REPLACEMENTS | (type != String.class ? Annotations.NO_EMPTY : 0));
              +079        this.description = annotations.getAnnotationValue(param, Description.class, Annotations.REPLACEMENTS | Annotations.DEFAULT_EMPTY);
              +080        this.conditions = annotations.getAnnotationValue(param, Conditions.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              +081
              +082        //noinspection unchecked
              +083        this.resolver = manager.getCommandContexts().getResolver(type);
              +084        if (this.resolver == null) {
              +085            ACFUtil.sneaky(new InvalidCommandContextException(
              +086                    "Parameter " + type.getSimpleName() + " of " + command + " has no applicable context resolver"
              +087            ));
              +088        }
              +089
              +090        this.optional = annotations.hasAnnotation(param, Optional.class) || this.defaultValue != null || (isLast && type == String[].class);
              +091        this.permission = annotations.getAnnotationValue(param, CommandPermission.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              +092        this.optionalResolver = isOptionalResolver(resolver);
              +093        this.requiresInput = !this.optional && !this.optionalResolver;
              +094        //noinspection unchecked
              +095        this.commandIssuer = paramIndex == 0 && manager.isCommandIssuer(type);
              +096        this.canConsumeInput = !this.commandIssuer && !(resolver instanceof IssuerOnlyContextResolver);
              +097        this.consumesRest = (type == String.class && !annotations.hasAnnotation(param, Single.class)) || (isLast && type == String[].class);
              +098
              +099        this.values = annotations.getAnnotationValues(param, Values.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              +100
              +101        this.syntax = null;
              +102        if (!commandIssuer) {
              +103            this.syntax = annotations.getAnnotationValue(param, Syntax.class);
              +104            if (syntax == null) {
              +105                if (!requiresInput && canConsumeInput) {
              +106                    this.syntax = "[" + name + "]";
              +107                } else if (requiresInput) {
              +108                    this.syntax = "<" + name + ">";
              +109                }
              +110            }
              +111        }
              +112
              +113        this.flags = new HashMap<>();
              +114        String flags = annotations.getAnnotationValue(param, Flags.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              +115        if (flags != null) {
              +116            parseFlags(flags);
              +117        }
              +118        inheritContextFlags(command.scope);
              +119        this.computePermissions();
              +120    }
              +121
              +122    private void inheritContextFlags(BaseCommand scope) {
              +123        if (!scope.contextFlags.isEmpty()) {
              +124            Class<?> pCls = this.type;
              +125            do {
              +126                parseFlags(scope.contextFlags.get(pCls));
              +127            } while ((pCls = pCls.getSuperclass()) != null);
              +128        }
              +129        if (scope.parentCommand != null) {
              +130            inheritContextFlags(scope.parentCommand);
              +131        }
              +132    }
              +133
              +134    private void parseFlags(String flags) {
              +135        if (flags != null) {
              +136            for (String s : ACFPatterns.COMMA.split(manager.getCommandReplacements().replace(flags))) {
              +137                String[] v = ACFPatterns.EQUALS.split(s, 2);
              +138                if (!this.flags.containsKey(v[0])) {
              +139                    this.flags.put(v[0], v.length > 1 ? v[1] : null);
              +140                }
              +141            }
              +142        }
              +143    }
              +144
              +145    private void computePermissions() {
              +146        this.permissions.clear();
              +147        if (this.permission != null && !this.permission.isEmpty()) {
              +148            this.permissions.addAll(Arrays.asList(ACFPatterns.COMMA.split(this.permission)));
              +149        }
              +150    }
              +151
              +152    private boolean isOptionalResolver(ContextResolver<?, CEC> resolver) {
              +153        return resolver instanceof IssuerAwareContextResolver
              +154                || resolver instanceof IssuerOnlyContextResolver
              +155                || resolver instanceof OptionalContextResolver;
              +156    }
              +157
              +158
              +159    public Parameter getParameter() {
              +160        return parameter;
              +161    }
              +162
              +163    public Class<?> getType() {
              +164        return type;
              +165    }
              +166
              +167    public String getName() {
              +168        return name;
              +169    }
              +170
              +171    public CommandManager getManager() {
              +172        return manager;
              +173    }
              +174
              +175    public int getParamIndex() {
              +176        return paramIndex;
              +177    }
              +178
              +179    public ContextResolver<?, CEC> getResolver() {
              +180        return resolver;
              +181    }
              +182
              +183    public void setResolver(ContextResolver<?, CEC> resolver) {
              +184        this.resolver = resolver;
              +185    }
              +186
              +187    public boolean isOptional() {
              +188        return optional;
              +189    }
              +190
              +191    public void setOptional(boolean optional) {
              +192        this.optional = optional;
              +193    }
              +194
              +195    public String getDescription() {
              +196        return description;
              +197    }
              +198
              +199    public void setDescription(String description) {
              +200        this.description = description;
              +201    }
              +202
              +203    public String getDefaultValue() {
              +204        return defaultValue;
              +205    }
              +206
              +207    public void setDefaultValue(String defaultValue) {
              +208        this.defaultValue = defaultValue;
              +209    }
              +210
              +211    public boolean isCommandIssuer() {
              +212        return commandIssuer;
              +213    }
              +214
              +215    public void setCommandIssuer(boolean commandIssuer) {
              +216        this.commandIssuer = commandIssuer;
              +217    }
              +218
              +219    public String[] getValues() {
              +220        return values;
              +221    }
              +222
              +223    public void setValues(String[] values) {
              +224        this.values = values;
              +225    }
              +226
              +227    public Map<String, String> getFlags() {
              +228        return flags;
              +229    }
              +230
              +231    public void setFlags(Map<String, String> flags) {
              +232        this.flags = flags;
              +233    }
              +234
              +235    public boolean canConsumeInput() {
              +236        return canConsumeInput;
              +237    }
              +238
              +239    public void setCanConsumeInput(boolean canConsumeInput) {
              +240        this.canConsumeInput = canConsumeInput;
              +241    }
              +242
              +243    public void setOptionalResolver(boolean optionalResolver) {
              +244        this.optionalResolver = optionalResolver;
              +245    }
              +246
              +247    public boolean isOptionalResolver() {
              +248        return optionalResolver;
              +249    }
              +250
              +251    public boolean requiresInput() {
              +252        return requiresInput;
              +253    }
              +254
              +255    public void setRequiresInput(boolean requiresInput) {
              +256        this.requiresInput = requiresInput;
              +257    }
              +258
              +259    public String getSyntax() {
              +260        return syntax;
              +261    }
              +262
              +263    public void setSyntax(String syntax) {
              +264        this.syntax = syntax;
              +265    }
              +266
              +267    public String getConditions() {
              +268        return conditions;
              +269    }
              +270
              +271    public void setConditions(String conditions) {
              +272        this.conditions = conditions;
              +273    }
              +274
              +275    public Set<String> getRequiredPermissions() {
              +276        return permissions;
              +277    }
              +278}
               
               
               
              @@ -346,5 +347,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/CommandReplacements.html b/docs/acf-core/src-html/co/aikar/commands/CommandReplacements.html index 27a0029c..38f5b639 100644 --- a/docs/acf-core/src-html/co/aikar/commands/CommandReplacements.html +++ b/docs/acf-core/src-html/co/aikar/commands/CommandReplacements.html @@ -1,104 +1,106 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import org.jetbrains.annotations.Nullable;
              -027
              -028import java.util.AbstractMap;
              -029import java.util.LinkedHashMap;
              -030import java.util.Map;
              -031import java.util.regex.Matcher;
              -032import java.util.regex.Pattern;
              -033
              -034/**
              -035 * Manages replacement template strings
              -036 */
              -037public class CommandReplacements {
              -038
              -039    private final CommandManager manager;
              -040    private final Map<String, Map.Entry<Pattern, String>> replacements = new LinkedHashMap<>();
              -041
              -042    CommandReplacements(CommandManager manager) {
              -043        this.manager = manager;
              -044        addReplacement0("truthy", "true|false|yes|no|1|0|on|off|t|f");
              -045    }
              -046
              -047    public void addReplacements(String... replacements) {
              -048        if (replacements.length == 0 || replacements.length % 2 != 0) {
              -049            throw new IllegalArgumentException("Must pass a number of arguments divisible by 2.");
              -050        }
              -051        for (int i = 0; i < replacements.length; i += 2) {
              -052            addReplacement(replacements[i], replacements[i+1]);
              -053        }
              -054    }
              -055
              -056    public String addReplacement(String key, String val) {
              -057        return addReplacement0(key, val);
              -058    }
              -059
              -060    @Nullable
              -061    private String addReplacement0(String key, String val) {
              -062        key = ACFPatterns.PERCENTAGE.matcher(key.toLowerCase()).replaceAll("");
              -063        Pattern pattern = Pattern.compile("%" + Pattern.quote(key) + "\\b", Pattern.CASE_INSENSITIVE);
              -064
              -065        Map.Entry<Pattern, String> entry = new AbstractMap.SimpleImmutableEntry<>(pattern, val);
              -066        Map.Entry<Pattern, String> replaced = replacements.put(key, entry);
              -067
              -068        if (replaced != null) {
              -069            return replaced.getValue();
              -070        }
              -071
              -072        return null;
              -073    }
              -074
              -075    public String replace(String text) {
              -076        if (text == null) {
              -077            return null;
              -078        }
              -079
              -080        for (Map.Entry<Pattern, String> entry : replacements.values()) {
              -081            text = entry.getKey().matcher(text).replaceAll(entry.getValue());
              -082        }
              -083
              -084        // check for unregistered replacements
              -085        Pattern pattern = Pattern.compile("%.[^\\s]*");
              -086        Matcher matcher = pattern.matcher(text);
              -087        while (matcher.find()) {
              -088            this.manager.log(LogLevel.ERROR, "Found unregistered replacement: " + matcher.group());
              -089        }
              -090
              -091        return text;
              -092    }
              -093}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import org.jetbrains.annotations.Nullable;
              +027
              +028import java.util.AbstractMap;
              +029import java.util.LinkedHashMap;
              +030import java.util.Locale;
              +031import java.util.Map;
              +032import java.util.regex.Matcher;
              +033import java.util.regex.Pattern;
              +034
              +035/**
              +036 * Manages replacement template strings
              +037 */
              +038public class CommandReplacements {
              +039
              +040    private final CommandManager manager;
              +041    private final Map<String, Map.Entry<Pattern, String>> replacements = new LinkedHashMap<>();
              +042
              +043    CommandReplacements(CommandManager manager) {
              +044        this.manager = manager;
              +045        addReplacement0("truthy", "true|false|yes|no|1|0|on|off|t|f");
              +046    }
              +047
              +048    public void addReplacements(String... replacements) {
              +049        if (replacements.length == 0 || replacements.length % 2 != 0) {
              +050            throw new IllegalArgumentException("Must pass a number of arguments divisible by 2.");
              +051        }
              +052        for (int i = 0; i < replacements.length; i += 2) {
              +053            addReplacement(replacements[i], replacements[i+1]);
              +054        }
              +055    }
              +056
              +057    public String addReplacement(String key, String val) {
              +058        return addReplacement0(key, val);
              +059    }
              +060
              +061    @Nullable
              +062    private String addReplacement0(String key, String val) {
              +063        key = ACFPatterns.PERCENTAGE.matcher(key.toLowerCase(Locale.ENGLISH)).replaceAll("");
              +064        Pattern pattern = Pattern.compile("%" + Pattern.quote(key) + "\\b", Pattern.CASE_INSENSITIVE);
              +065
              +066        Map.Entry<Pattern, String> entry = new AbstractMap.SimpleImmutableEntry<>(pattern, val);
              +067        Map.Entry<Pattern, String> replaced = replacements.put(key, entry);
              +068
              +069        if (replaced != null) {
              +070            return replaced.getValue();
              +071        }
              +072
              +073        return null;
              +074    }
              +075
              +076    public String replace(String text) {
              +077        if (text == null) {
              +078            return null;
              +079        }
              +080
              +081        for (Map.Entry<Pattern, String> entry : replacements.values()) {
              +082            text = entry.getKey().matcher(text).replaceAll(entry.getValue());
              +083        }
              +084
              +085        // check for unregistered replacements
              +086        Pattern pattern = Pattern.compile("%.[^\\s]*");
              +087        Matcher matcher = pattern.matcher(text);
              +088        while (matcher.find()) {
              +089            this.manager.log(LogLevel.ERROR, "Found unregistered replacement: " + matcher.group());
              +090        }
              +091
              +092        return text;
              +093    }
              +094}
               
               
               
              @@ -161,5 +163,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/ConditionContext.html b/docs/acf-core/src-html/co/aikar/commands/ConditionContext.html index 5385a1ca..6fb887bf 100644 --- a/docs/acf-core/src-html/co/aikar/commands/ConditionContext.html +++ b/docs/acf-core/src-html/co/aikar/commands/ConditionContext.html @@ -1,77 +1,78 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import java.util.HashMap;
              -027import java.util.Map;
              -028
              -029public class ConditionContext <I extends CommandIssuer> {
              -030
              -031    private final I issuer;
              -032    private final String config;
              -033    private final Map<String, String> configs;
              -034
              -035    ConditionContext(I issuer, String config) {
              -036        this.issuer = issuer;
              -037        this.config = config;
              -038        this.configs = new HashMap<>();
              -039        if (config != null) {
              -040            for (String s : ACFPatterns.COMMA.split(config)) {
              -041                String[] v = ACFPatterns.EQUALS.split(s, 2);
              -042                this.configs.put(v[0], v.length > 1 ? v[1] : null);
              -043            }
              -044        }
              -045    }
              -046
              -047
              -048    public I getIssuer() {
              -049        return issuer;
              -050    }
              -051
              -052    public String getConfig() {
              -053        return this.config;
              -054    }
              -055    public boolean hasConfig(String flag) {
              -056        return configs.containsKey(flag);
              -057    }
              -058
              -059    public String getConfigValue(String flag, String def) {
              -060        return configs.getOrDefault(flag, def);
              -061    }
              -062
              -063    public Integer getConfigValue(String flag, Integer def) {
              -064        return ACFUtil.parseInt(this.configs.get(flag), def);
              -065    }
              -066}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import java.util.HashMap;
              +027import java.util.Map;
              +028
              +029public class ConditionContext <I extends CommandIssuer> {
              +030
              +031    private final I issuer;
              +032    private final String config;
              +033    private final Map<String, String> configs;
              +034
              +035    ConditionContext(I issuer, String config) {
              +036        this.issuer = issuer;
              +037        this.config = config;
              +038        this.configs = new HashMap<>();
              +039        if (config != null) {
              +040            for (String s : ACFPatterns.COMMA.split(config)) {
              +041                String[] v = ACFPatterns.EQUALS.split(s, 2);
              +042                this.configs.put(v[0], v.length > 1 ? v[1] : null);
              +043            }
              +044        }
              +045    }
              +046
              +047
              +048    public I getIssuer() {
              +049        return issuer;
              +050    }
              +051
              +052    public String getConfig() {
              +053        return this.config;
              +054    }
              +055    public boolean hasConfig(String flag) {
              +056        return configs.containsKey(flag);
              +057    }
              +058
              +059    public String getConfigValue(String flag, String def) {
              +060        return configs.getOrDefault(flag, def);
              +061    }
              +062
              +063    public Integer getConfigValue(String flag, Integer def) {
              +064        return ACFUtil.parseInt(this.configs.get(flag), def);
              +065    }
              +066}
               
               
               
              @@ -134,5 +135,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/ConditionFailedException.html b/docs/acf-core/src-html/co/aikar/commands/ConditionFailedException.html index 2d6df073..d6cee759 100644 --- a/docs/acf-core/src-html/co/aikar/commands/ConditionFailedException.html +++ b/docs/acf-core/src-html/co/aikar/commands/ConditionFailedException.html @@ -1,56 +1,57 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.locales.MessageKey;
              -027import co.aikar.locales.MessageKeyProvider;
              -028
              -029public class ConditionFailedException extends InvalidCommandArgument {
              -030    public ConditionFailedException() {
              -031        super(false);
              -032    }
              -033
              -034    public ConditionFailedException(MessageKeyProvider key, String... replacements) {
              -035        super(key, false, replacements);
              -036    }
              -037
              -038    public ConditionFailedException(MessageKey key, String... replacements) {
              -039        super(key, false, replacements);
              -040    }
              -041
              -042    public ConditionFailedException(String message) {
              -043        super(message, false);
              -044    }
              -045}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.locales.MessageKey;
              +027import co.aikar.locales.MessageKeyProvider;
              +028
              +029public class ConditionFailedException extends InvalidCommandArgument {
              +030    public ConditionFailedException() {
              +031        super(false);
              +032    }
              +033
              +034    public ConditionFailedException(MessageKeyProvider key, String... replacements) {
              +035        super(key, false, replacements);
              +036    }
              +037
              +038    public ConditionFailedException(MessageKey key, String... replacements) {
              +039        super(key, false, replacements);
              +040    }
              +041
              +042    public ConditionFailedException(String message) {
              +043        super(message, false);
              +044    }
              +045}
               
               
               
              @@ -113,5 +114,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/ExceptionHandler.html b/docs/acf-core/src-html/co/aikar/commands/ExceptionHandler.html index d723c5da..891bc73f 100644 --- a/docs/acf-core/src-html/co/aikar/commands/ExceptionHandler.html +++ b/docs/acf-core/src-html/co/aikar/commands/ExceptionHandler.html @@ -1,59 +1,60 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import java.util.List;
              -027
              -028/**
              -029 * Functional interface to allow plugins to handle uncaught excetpions
              -030 */
              -031@FunctionalInterface
              -032public interface ExceptionHandler {
              -033
              -034  /**
              -035   * Called when an exception occurs while executing a command<br>
              -036   * If an exception handler properly handles an exception, the user will not be noticied by the
              -037   * framework that something went unexceptected.
              -038   *
              -039   * @param command the command that was executed
              -040   * @param registeredCommand the registered command
              -041   * @param sender the issuer who send the command
              -042   * @param args the args he used
              -043   * @param t the throwable that caused this exception
              -044   *
              -045   * @return if the exception was handeled by the exception handler.
              -046   */
              -047  boolean execute(BaseCommand command, RegisteredCommand registeredCommand, CommandIssuer sender, List<String> args, Throwable t);
              -048}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import java.util.List;
              +027
              +028/**
              +029 * Functional interface to allow plugins to handle uncaught excetpions
              +030 */
              +031@FunctionalInterface
              +032public interface ExceptionHandler {
              +033
              +034  /**
              +035   * Called when an exception occurs while executing a command<br>
              +036   * If an exception handler properly handles an exception, the user will not be noticied by the
              +037   * framework that something went unexceptected.
              +038   *
              +039   * @param command the command that was executed
              +040   * @param registeredCommand the registered command
              +041   * @param sender the issuer who send the command
              +042   * @param args the args he used
              +043   * @param t the throwable that caused this exception
              +044   *
              +045   * @return if the exception was handeled by the exception handler.
              +046   */
              +047  boolean execute(BaseCommand command, RegisteredCommand registeredCommand, CommandIssuer sender, List<String> args, Throwable t);
              +048}
               
               
               
              @@ -116,5 +117,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/ForwardingCommand.html b/docs/acf-core/src-html/co/aikar/commands/ForwardingCommand.html index 59b9d0c5..aaa2e755 100644 --- a/docs/acf-core/src-html/co/aikar/commands/ForwardingCommand.html +++ b/docs/acf-core/src-html/co/aikar/commands/ForwardingCommand.html @@ -1,101 +1,102 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              -027
              -028import java.util.Collections;
              -029import java.util.List;
              -030import java.util.Set;
              -031
              -032public class ForwardingCommand extends BaseCommand {
              -033    private final BaseCommand command;
              -034    private final String[] baseArgs;
              -035    private final RegisteredCommand regCommand;
              -036
              -037    ForwardingCommand(BaseCommand baseCommand, RegisteredCommand regCommand, String[] baseArgs) {
              -038        this.regCommand = regCommand;
              -039        this.commandName = baseCommand.commandName;
              -040        this.command = baseCommand;
              -041        this.baseArgs = baseArgs;
              -042        this.manager = baseCommand.manager;
              -043        this.subCommands.put(DEFAULT, regCommand);
              -044    }
              -045
              -046    @Override
              -047    public List<RegisteredCommand> getRegisteredCommands() {
              -048        return Collections.singletonList(regCommand);
              -049    }
              -050
              -051    @Override
              -052    public CommandOperationContext getLastCommandOperationContext() {
              -053        return command.getLastCommandOperationContext();
              -054    }
              -055
              -056    @Override
              -057    public Set<String> getRequiredPermissions() {
              -058        return command.getRequiredPermissions();
              -059    }
              -060
              -061    @Override
              -062    public boolean hasPermission(Object issuer) {
              -063        return command.hasPermission(issuer);
              -064    }
              -065
              -066    @Override
              -067    public boolean requiresPermission(String permission) {
              -068        return command.requiresPermission(permission);
              -069    }
              -070
              -071    @Override
              -072    public boolean hasPermission(CommandIssuer sender) {
              -073        return command.hasPermission(sender);
              -074    }
              -075
              -076    @Override
              -077    public List<String> tabComplete(CommandIssuer issuer, RootCommand rootCommand, String[] args, boolean isAsync) throws IllegalArgumentException {
              -078        return command.tabComplete(issuer, rootCommand, args, isAsync);
              -079    }
              -080
              -081    @Override
              -082    public void execute(CommandIssuer issuer, CommandRouter.CommandRouteResult result) {
              -083        result = new CommandRouter.CommandRouteResult(regCommand, result.args, ACFUtil.join(baseArgs), result.commandLabel);
              -084        command.execute(issuer, result);
              -085    }
              -086
              -087    BaseCommand getCommand() {
              -088        return command;
              -089    }
              -090}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
              +027
              +028import java.util.Collections;
              +029import java.util.List;
              +030import java.util.Set;
              +031
              +032public class ForwardingCommand extends BaseCommand {
              +033    private final BaseCommand command;
              +034    private final String[] baseArgs;
              +035    private final RegisteredCommand regCommand;
              +036
              +037    ForwardingCommand(BaseCommand baseCommand, RegisteredCommand regCommand, String[] baseArgs) {
              +038        this.regCommand = regCommand;
              +039        this.commandName = baseCommand.commandName;
              +040        this.command = baseCommand;
              +041        this.baseArgs = baseArgs;
              +042        this.manager = baseCommand.manager;
              +043        this.subCommands.put(DEFAULT, regCommand);
              +044    }
              +045
              +046    @Override
              +047    public List<RegisteredCommand> getRegisteredCommands() {
              +048        return Collections.singletonList(regCommand);
              +049    }
              +050
              +051    @Override
              +052    public CommandOperationContext getLastCommandOperationContext() {
              +053        return command.getLastCommandOperationContext();
              +054    }
              +055
              +056    @Override
              +057    public Set<String> getRequiredPermissions() {
              +058        return command.getRequiredPermissions();
              +059    }
              +060
              +061    @Override
              +062    public boolean hasPermission(Object issuer) {
              +063        return command.hasPermission(issuer);
              +064    }
              +065
              +066    @Override
              +067    public boolean requiresPermission(String permission) {
              +068        return command.requiresPermission(permission);
              +069    }
              +070
              +071    @Override
              +072    public boolean hasPermission(CommandIssuer sender) {
              +073        return command.hasPermission(sender);
              +074    }
              +075
              +076    @Override
              +077    public List<String> tabComplete(CommandIssuer issuer, RootCommand rootCommand, String[] args, boolean isAsync) throws IllegalArgumentException {
              +078        return command.tabComplete(issuer, rootCommand, args, isAsync);
              +079    }
              +080
              +081    @Override
              +082    public void execute(CommandIssuer issuer, CommandRouter.CommandRouteResult result) {
              +083        result = new CommandRouter.CommandRouteResult(regCommand, result.args, ACFUtil.join(baseArgs), result.commandLabel);
              +084        command.execute(issuer, result);
              +085    }
              +086
              +087    BaseCommand getCommand() {
              +088        return command;
              +089    }
              +090}
               
               
               
              @@ -158,5 +159,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/HelpEntry.html b/docs/acf-core/src-html/co/aikar/commands/HelpEntry.html index adccce04..88f284ed 100644 --- a/docs/acf-core/src-html/co/aikar/commands/HelpEntry.html +++ b/docs/acf-core/src-html/co/aikar/commands/HelpEntry.html @@ -1,87 +1,88 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026public class HelpEntry {
              -027
              -028    private final CommandHelp commandHelp;
              -029    private final RegisteredCommand command;
              -030    private int searchScore = 1;
              -031
              -032    HelpEntry(CommandHelp commandHelp, RegisteredCommand command) {
              -033        this.commandHelp = commandHelp;
              -034        this.command = command;
              -035    }
              -036
              -037    RegisteredCommand getRegisteredCommand() {
              -038        return this.command;
              -039    }
              -040
              -041    public String getCommand() {
              -042        return this.command.command;
              -043    }
              -044
              -045    public String getCommandPrefix() {
              -046        return this.commandHelp.getCommandPrefix();
              -047    }
              -048
              -049    public String getParameterSyntax(){
              -050        return this.command.syntaxText != null ? this.command.syntaxText : "";
              -051    }
              -052
              -053    public String getDescription(){
              -054        return this.command.getHelpText();
              -055    }
              -056
              -057    public void setSearchScore(int searchScore) {
              -058        this.searchScore = searchScore;
              -059    }
              -060
              -061    public boolean shouldShow() {
              -062        return this.searchScore > 0;
              -063    }
              -064
              -065    public int getSearchScore() {
              -066        return searchScore;
              -067    }
              -068
              -069    public String getSearchTags() {
              -070        return command.helpSearchTags;
              -071    }
              -072
              -073    public CommandParameter[] getParameters() {
              -074        return command.parameters;
              -075    }
              -076}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026public class HelpEntry {
              +027
              +028    private final CommandHelp commandHelp;
              +029    private final RegisteredCommand command;
              +030    private int searchScore = 1;
              +031
              +032    HelpEntry(CommandHelp commandHelp, RegisteredCommand command) {
              +033        this.commandHelp = commandHelp;
              +034        this.command = command;
              +035    }
              +036
              +037    RegisteredCommand getRegisteredCommand() {
              +038        return this.command;
              +039    }
              +040
              +041    public String getCommand() {
              +042        return this.command.command;
              +043    }
              +044
              +045    public String getCommandPrefix() {
              +046        return this.commandHelp.getCommandPrefix();
              +047    }
              +048
              +049    public String getParameterSyntax(){
              +050        return this.command.syntaxText != null ? this.command.syntaxText : "";
              +051    }
              +052
              +053    public String getDescription(){
              +054        return this.command.getHelpText();
              +055    }
              +056
              +057    public void setSearchScore(int searchScore) {
              +058        this.searchScore = searchScore;
              +059    }
              +060
              +061    public boolean shouldShow() {
              +062        return this.searchScore > 0;
              +063    }
              +064
              +065    public int getSearchScore() {
              +066        return searchScore;
              +067    }
              +068
              +069    public String getSearchTags() {
              +070        return command.helpSearchTags;
              +071    }
              +072
              +073    public CommandParameter[] getParameters() {
              +074        return command.parameters;
              +075    }
              +076}
               
               
               
              @@ -144,5 +145,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/InvalidCommandArgument.html b/docs/acf-core/src-html/co/aikar/commands/InvalidCommandArgument.html index 70f13441..f44ddc33 100644 --- a/docs/acf-core/src-html/co/aikar/commands/InvalidCommandArgument.html +++ b/docs/acf-core/src-html/co/aikar/commands/InvalidCommandArgument.html @@ -1,82 +1,83 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.locales.MessageKey;
              -027import co.aikar.locales.MessageKeyProvider;
              -028
              -029public class InvalidCommandArgument extends RuntimeException {
              -030    final boolean showSyntax;
              -031    final MessageKey key;
              -032    final String[] replacements;
              -033
              -034    public InvalidCommandArgument() {
              -035        this(null, true);
              -036    }
              -037
              -038    public InvalidCommandArgument(boolean showSyntax) {
              -039        this(null, showSyntax);
              -040    }
              -041
              -042    public InvalidCommandArgument(MessageKeyProvider key, String... replacements) {
              -043        this(key.getMessageKey(), replacements);
              -044    }
              -045
              -046    public InvalidCommandArgument(MessageKey key, String... replacements) {
              -047        this(key, true, replacements);
              -048    }
              -049
              -050    public InvalidCommandArgument(MessageKeyProvider key, boolean showSyntax, String... replacements) {
              -051        this(key.getMessageKey(), showSyntax, replacements);
              -052    }
              -053
              -054    public InvalidCommandArgument(MessageKey key, boolean showSyntax, String... replacements) {
              -055        super(key.getKey(), null, false, false);
              -056        this.showSyntax = showSyntax;
              -057        this.key = key;
              -058        this.replacements = replacements;
              -059    }
              -060
              -061    public InvalidCommandArgument(String message) {
              -062        this(message, true);
              -063    }
              -064
              -065    public InvalidCommandArgument(String message, boolean showSyntax) {
              -066        super(message, null, false, false);
              -067        this.showSyntax = showSyntax;
              -068        this.replacements = null;
              -069        this.key = null;
              -070    }
              -071}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.locales.MessageKey;
              +027import co.aikar.locales.MessageKeyProvider;
              +028
              +029public class InvalidCommandArgument extends RuntimeException {
              +030    final boolean showSyntax;
              +031    final MessageKey key;
              +032    final String[] replacements;
              +033
              +034    public InvalidCommandArgument() {
              +035        this(null, true);
              +036    }
              +037
              +038    public InvalidCommandArgument(boolean showSyntax) {
              +039        this(null, showSyntax);
              +040    }
              +041
              +042    public InvalidCommandArgument(MessageKeyProvider key, String... replacements) {
              +043        this(key.getMessageKey(), replacements);
              +044    }
              +045
              +046    public InvalidCommandArgument(MessageKey key, String... replacements) {
              +047        this(key, true, replacements);
              +048    }
              +049
              +050    public InvalidCommandArgument(MessageKeyProvider key, boolean showSyntax, String... replacements) {
              +051        this(key.getMessageKey(), showSyntax, replacements);
              +052    }
              +053
              +054    public InvalidCommandArgument(MessageKey key, boolean showSyntax, String... replacements) {
              +055        super(key.getKey(), null, false, false);
              +056        this.showSyntax = showSyntax;
              +057        this.key = key;
              +058        this.replacements = replacements;
              +059    }
              +060
              +061    public InvalidCommandArgument(String message) {
              +062        this(message, true);
              +063    }
              +064
              +065    public InvalidCommandArgument(String message, boolean showSyntax) {
              +066        super(message, null, false, false);
              +067        this.showSyntax = showSyntax;
              +068        this.replacements = null;
              +069        this.key = null;
              +070    }
              +071}
               
               
               
              @@ -139,5 +140,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/InvalidCommandContextException.html b/docs/acf-core/src-html/co/aikar/commands/InvalidCommandContextException.html index 9b3f036e..9d6143c4 100644 --- a/docs/acf-core/src-html/co/aikar/commands/InvalidCommandContextException.html +++ b/docs/acf-core/src-html/co/aikar/commands/InvalidCommandContextException.html @@ -1,41 +1,42 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026public class InvalidCommandContextException extends RuntimeException {
              -027    InvalidCommandContextException(String message) {
              -028        super(message);
              -029    }
              -030}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026public class InvalidCommandContextException extends RuntimeException {
              +027    InvalidCommandContextException(String message) {
              +028        super(message);
              +029    }
              +030}
               
               
               
              @@ -98,5 +99,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/IssuerLocaleChangedCallback.html b/docs/acf-core/src-html/co/aikar/commands/IssuerLocaleChangedCallback.html index a7c90d49..9935b66b 100644 --- a/docs/acf-core/src-html/co/aikar/commands/IssuerLocaleChangedCallback.html +++ b/docs/acf-core/src-html/co/aikar/commands/IssuerLocaleChangedCallback.html @@ -1,41 +1,42 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import java.util.Locale;
              -027
              -028public interface IssuerLocaleChangedCallback <I extends CommandIssuer> {
              -029    void onIssuerLocaleChange(I issuer, Locale oldLocale, Locale newLocale);
              -030}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import java.util.Locale;
              +027
              +028public interface IssuerLocaleChangedCallback <I extends CommandIssuer> {
              +029    void onIssuerLocaleChange(I issuer, Locale oldLocale, Locale newLocale);
              +030}
               
               
               
              @@ -98,5 +99,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/Locales.html b/docs/acf-core/src-html/co/aikar/commands/Locales.html index f7b6b39f..2b83b116 100644 --- a/docs/acf-core/src-html/co/aikar/commands/Locales.html +++ b/docs/acf-core/src-html/co/aikar/commands/Locales.html @@ -1,219 +1,220 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.locales.LocaleManager;
              -027import co.aikar.locales.MessageKey;
              -028import co.aikar.locales.MessageKeyProvider;
              -029import com.google.common.collect.HashMultimap;
              -030import com.google.common.collect.SetMultimap;
              -031import org.jetbrains.annotations.NotNull;
              -032
              -033import java.util.ArrayList;
              -034import java.util.HashMap;
              -035import java.util.HashSet;
              -036import java.util.LinkedHashMap;
              -037import java.util.List;
              -038import java.util.Locale;
              -039import java.util.Map;
              -040import java.util.Set;
              -041import java.util.regex.Matcher;
              -042
              -043@SuppressWarnings("WeakerAccess")
              -044public class Locales {
              -045    // Locales for reference since Locale doesn't have as many, add our own here for ease of use.
              -046    public static final Locale ENGLISH = Locale.ENGLISH;
              -047    public static final Locale GERMAN = Locale.GERMAN;
              -048    public static final Locale FRENCH = Locale.FRENCH;
              -049    public static final Locale JAPANESE = Locale.JAPANESE;
              -050    public static final Locale ITALIAN = Locale.ITALIAN;
              -051    public static final Locale KOREAN = Locale.KOREAN;
              -052    public static final Locale CHINESE = Locale.CHINESE;
              -053    public static final Locale SIMPLIFIED_CHINESE = Locale.SIMPLIFIED_CHINESE;
              -054    public static final Locale TRADITIONAL_CHINESE = Locale.TRADITIONAL_CHINESE;
              -055    public static final Locale SPANISH = new Locale("es");
              -056    public static final Locale DUTCH = new Locale("nl");
              -057    public static final Locale DANISH = new Locale("da");
              -058    public static final Locale CZECH = new Locale("cs");
              -059    public static final Locale GREEK = new Locale("el");
              -060    public static final Locale LATIN = new Locale("la");
              -061    public static final Locale BULGARIAN = new Locale("bg");
              -062    public static final Locale AFRIKAANS = new Locale("af");
              -063    public static final Locale HINDI = new Locale("hi");
              -064    public static final Locale HEBREW = new Locale("he");
              -065    public static final Locale POLISH = new Locale("pl");
              -066    public static final Locale PORTUGUESE = new Locale("pt");
              -067    public static final Locale FINNISH = new Locale("fi");
              -068    public static final Locale SWEDISH = new Locale("sv");
              -069    public static final Locale RUSSIAN = new Locale("ru");
              -070    public static final Locale ROMANIAN = new Locale("ro");
              -071    public static final Locale VIETNAMESE = new Locale("vi");
              -072    public static final Locale THAI = new Locale("th");
              -073    public static final Locale TURKISH = new Locale("tr");
              -074    public static final Locale UKRANIAN = new Locale("uk");
              -075    public static final Locale ARABIC = new Locale("ar");
              -076    public static final Locale WELSH = new Locale("cy");
              -077    public static final Locale NORWEGIAN_BOKMAAL = new Locale("nb");
              -078    public static final Locale NORWEGIAN_NYNORSK = new Locale("nn");
              -079    public static final Locale HUNGARIAN = new Locale("hu");
              -080
              -081    private final CommandManager manager;
              -082    private final LocaleManager<CommandIssuer> localeManager;
              -083    private final Map<ClassLoader, SetMultimap<String, Locale>> loadedBundles = new HashMap<>();
              -084    private final List<ClassLoader> registeredClassLoaders = new ArrayList<>();
              -085
              -086    public Locales(CommandManager manager) {
              -087        this.manager = manager;
              -088        this.localeManager = LocaleManager.create(manager::getIssuerLocale);
              -089        this.addBundleClassLoader(this.getClass().getClassLoader());
              -090    }
              -091
              -092    public void loadLanguages() {
              -093        addMessageBundles("acf-core");
              -094    }
              -095
              -096    public Locale getDefaultLocale() {
              -097        return this.localeManager.getDefaultLocale();
              -098    }
              -099
              -100    public Locale setDefaultLocale(Locale locale) {
              -101        return this.localeManager.setDefaultLocale(locale);
              -102    }
              -103
              -104    /**
              -105     * Looks for all previously loaded bundles, and if any new Supported Languages have been added, load them.
              -106     */
              -107    public void loadMissingBundles() {
              -108        //noinspection unchecked
              -109        Set<Locale> supportedLanguages = manager.getSupportedLanguages();
              -110        for (Locale locale : supportedLanguages) {
              -111            for(SetMultimap<String, Locale> localeData: this.loadedBundles.values()) {
              -112                for (String bundleName : new HashSet<>(localeData.keys())) {
              -113                    addMessageBundle(bundleName, locale);
              -114                }
              -115            }
              -116
              -117        }
              -118    }
              -119
              -120    public void addMessageBundles(String... bundleNames) {
              -121        for (String bundleName : bundleNames) {
              -122            //noinspection unchecked
              -123            Set<Locale> supportedLanguages = manager.getSupportedLanguages();
              -124            for (Locale locale : supportedLanguages) {
              -125                addMessageBundle(bundleName, locale);
              -126            }
              -127        }
              -128    }
              -129
              -130    public boolean addMessageBundle(String bundleName, Locale locale) {
              -131        boolean found = false;
              -132        for(ClassLoader classLoader: this.registeredClassLoaders) {
              -133            if(this.addMessageBundle(classLoader, bundleName, locale)) {
              -134                found = true;
              -135            }
              -136        }
              -137
              -138        return found;
              -139    }
              -140
              -141    public boolean addMessageBundle(ClassLoader classLoader, String bundleName, Locale locale) {
              -142        SetMultimap<String, Locale> classLoadersLocales = this.loadedBundles.getOrDefault(classLoader, HashMultimap.create());
              -143        if(!classLoadersLocales.containsEntry(bundleName, locale)) {
              -144            if(this.localeManager.addMessageBundle(classLoader, bundleName, locale)) {
              -145                classLoadersLocales.put(bundleName, locale);
              -146                this.loadedBundles.put(classLoader, classLoadersLocales);
              -147                return true;
              -148            }
              -149        }
              -150
              -151        return false;
              -152    }
              -153
              -154    public void addMessageStrings(Locale locale, @NotNull Map<String, String> messages) {
              -155        Map<MessageKey, String> map = new HashMap<>(messages.size());
              -156        messages.forEach((key, value) -> map.put(MessageKey.of(key), value));
              -157        this.localeManager.addMessages(locale, map);
              -158    }
              -159
              -160    public void addMessages(Locale locale, @NotNull Map<? extends MessageKeyProvider, String> messages) {
              -161        Map<MessageKey, String> messagesMap = new LinkedHashMap<>();
              -162        for (Map.Entry<? extends MessageKeyProvider, String> entry : messages.entrySet()) {
              -163            messagesMap.put(entry.getKey().getMessageKey(), entry.getValue());
              -164        }
              -165
              -166        this.localeManager.addMessages(locale, messagesMap);
              -167    }
              -168
              -169    public String addMessage(Locale locale, MessageKeyProvider key, String message) {
              -170        return this.localeManager.addMessage(locale, key.getMessageKey(), message);
              -171    }
              -172
              -173    public String getMessage(CommandIssuer issuer, MessageKeyProvider key) {
              -174        final MessageKey msgKey = key.getMessageKey();
              -175        String message = this.localeManager.getMessage(issuer, msgKey);
              -176        if (message == null) {
              -177            manager.log(LogLevel.ERROR, "Missing Language Key: " + msgKey.getKey());
              -178            message = "<MISSING_LANGUAGE_KEY:" + msgKey.getKey() + ">";
              -179        }
              -180        return message;
              -181    }
              -182
              -183    public String replaceI18NStrings(String message) {
              -184        if (message == null) {
              -185            return null;
              -186        }
              -187        Matcher matcher = ACFPatterns.I18N_STRING.matcher(message);
              -188        if (!matcher.find()) {
              -189            return message;
              -190        }
              -191
              -192        CommandIssuer issuer = CommandManager.getCurrentCommandIssuer();
              -193
              -194        matcher.reset();
              -195        StringBuffer sb = new StringBuffer(message.length());
              -196        while (matcher.find()) {
              -197            MessageKey key = MessageKey.of(matcher.group("key"));
              -198            matcher.appendReplacement(sb, Matcher.quoteReplacement(getMessage(issuer, key)));
              -199        }
              -200        matcher.appendTail(sb);
              -201        return sb.toString();
              -202    }
              -203
              -204    public boolean addBundleClassLoader(ClassLoader classLoader) {
              -205        return !this.registeredClassLoaders.contains(classLoader) && this.registeredClassLoaders.add(classLoader);
              -206
              -207    }
              -208}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.locales.LocaleManager;
              +027import co.aikar.locales.MessageKey;
              +028import co.aikar.locales.MessageKeyProvider;
              +029import com.google.common.collect.HashMultimap;
              +030import com.google.common.collect.SetMultimap;
              +031import org.jetbrains.annotations.NotNull;
              +032
              +033import java.util.ArrayList;
              +034import java.util.HashMap;
              +035import java.util.HashSet;
              +036import java.util.LinkedHashMap;
              +037import java.util.List;
              +038import java.util.Locale;
              +039import java.util.Map;
              +040import java.util.Set;
              +041import java.util.regex.Matcher;
              +042
              +043@SuppressWarnings("WeakerAccess")
              +044public class Locales {
              +045    // Locales for reference since Locale doesn't have as many, add our own here for ease of use.
              +046    public static final Locale ENGLISH = Locale.ENGLISH;
              +047    public static final Locale GERMAN = Locale.GERMAN;
              +048    public static final Locale FRENCH = Locale.FRENCH;
              +049    public static final Locale JAPANESE = Locale.JAPANESE;
              +050    public static final Locale ITALIAN = Locale.ITALIAN;
              +051    public static final Locale KOREAN = Locale.KOREAN;
              +052    public static final Locale CHINESE = Locale.CHINESE;
              +053    public static final Locale SIMPLIFIED_CHINESE = Locale.SIMPLIFIED_CHINESE;
              +054    public static final Locale TRADITIONAL_CHINESE = Locale.TRADITIONAL_CHINESE;
              +055    public static final Locale SPANISH = new Locale("es");
              +056    public static final Locale DUTCH = new Locale("nl");
              +057    public static final Locale DANISH = new Locale("da");
              +058    public static final Locale CZECH = new Locale("cs");
              +059    public static final Locale GREEK = new Locale("el");
              +060    public static final Locale LATIN = new Locale("la");
              +061    public static final Locale BULGARIAN = new Locale("bg");
              +062    public static final Locale AFRIKAANS = new Locale("af");
              +063    public static final Locale HINDI = new Locale("hi");
              +064    public static final Locale HEBREW = new Locale("he");
              +065    public static final Locale POLISH = new Locale("pl");
              +066    public static final Locale PORTUGUESE = new Locale("pt");
              +067    public static final Locale FINNISH = new Locale("fi");
              +068    public static final Locale SWEDISH = new Locale("sv");
              +069    public static final Locale RUSSIAN = new Locale("ru");
              +070    public static final Locale ROMANIAN = new Locale("ro");
              +071    public static final Locale VIETNAMESE = new Locale("vi");
              +072    public static final Locale THAI = new Locale("th");
              +073    public static final Locale TURKISH = new Locale("tr");
              +074    public static final Locale UKRANIAN = new Locale("uk");
              +075    public static final Locale ARABIC = new Locale("ar");
              +076    public static final Locale WELSH = new Locale("cy");
              +077    public static final Locale NORWEGIAN_BOKMAAL = new Locale("nb");
              +078    public static final Locale NORWEGIAN_NYNORSK = new Locale("nn");
              +079    public static final Locale HUNGARIAN = new Locale("hu");
              +080
              +081    private final CommandManager manager;
              +082    private final LocaleManager<CommandIssuer> localeManager;
              +083    private final Map<ClassLoader, SetMultimap<String, Locale>> loadedBundles = new HashMap<>();
              +084    private final List<ClassLoader> registeredClassLoaders = new ArrayList<>();
              +085
              +086    public Locales(CommandManager manager) {
              +087        this.manager = manager;
              +088        this.localeManager = LocaleManager.create(manager::getIssuerLocale);
              +089        this.addBundleClassLoader(this.getClass().getClassLoader());
              +090    }
              +091
              +092    public void loadLanguages() {
              +093        addMessageBundles("acf-core");
              +094    }
              +095
              +096    public Locale getDefaultLocale() {
              +097        return this.localeManager.getDefaultLocale();
              +098    }
              +099
              +100    public Locale setDefaultLocale(Locale locale) {
              +101        return this.localeManager.setDefaultLocale(locale);
              +102    }
              +103
              +104    /**
              +105     * Looks for all previously loaded bundles, and if any new Supported Languages have been added, load them.
              +106     */
              +107    public void loadMissingBundles() {
              +108        //noinspection unchecked
              +109        Set<Locale> supportedLanguages = manager.getSupportedLanguages();
              +110        for (Locale locale : supportedLanguages) {
              +111            for(SetMultimap<String, Locale> localeData: this.loadedBundles.values()) {
              +112                for (String bundleName : new HashSet<>(localeData.keys())) {
              +113                    addMessageBundle(bundleName, locale);
              +114                }
              +115            }
              +116
              +117        }
              +118    }
              +119
              +120    public void addMessageBundles(String... bundleNames) {
              +121        for (String bundleName : bundleNames) {
              +122            //noinspection unchecked
              +123            Set<Locale> supportedLanguages = manager.getSupportedLanguages();
              +124            for (Locale locale : supportedLanguages) {
              +125                addMessageBundle(bundleName, locale);
              +126            }
              +127        }
              +128    }
              +129
              +130    public boolean addMessageBundle(String bundleName, Locale locale) {
              +131        boolean found = false;
              +132        for(ClassLoader classLoader: this.registeredClassLoaders) {
              +133            if(this.addMessageBundle(classLoader, bundleName, locale)) {
              +134                found = true;
              +135            }
              +136        }
              +137
              +138        return found;
              +139    }
              +140
              +141    public boolean addMessageBundle(ClassLoader classLoader, String bundleName, Locale locale) {
              +142        SetMultimap<String, Locale> classLoadersLocales = this.loadedBundles.getOrDefault(classLoader, HashMultimap.create());
              +143        if(!classLoadersLocales.containsEntry(bundleName, locale)) {
              +144            if(this.localeManager.addMessageBundle(classLoader, bundleName, locale)) {
              +145                classLoadersLocales.put(bundleName, locale);
              +146                this.loadedBundles.put(classLoader, classLoadersLocales);
              +147                return true;
              +148            }
              +149        }
              +150
              +151        return false;
              +152    }
              +153
              +154    public void addMessageStrings(Locale locale, @NotNull Map<String, String> messages) {
              +155        Map<MessageKey, String> map = new HashMap<>(messages.size());
              +156        messages.forEach((key, value) -> map.put(MessageKey.of(key), value));
              +157        this.localeManager.addMessages(locale, map);
              +158    }
              +159
              +160    public void addMessages(Locale locale, @NotNull Map<? extends MessageKeyProvider, String> messages) {
              +161        Map<MessageKey, String> messagesMap = new LinkedHashMap<>();
              +162        for (Map.Entry<? extends MessageKeyProvider, String> entry : messages.entrySet()) {
              +163            messagesMap.put(entry.getKey().getMessageKey(), entry.getValue());
              +164        }
              +165
              +166        this.localeManager.addMessages(locale, messagesMap);
              +167    }
              +168
              +169    public String addMessage(Locale locale, MessageKeyProvider key, String message) {
              +170        return this.localeManager.addMessage(locale, key.getMessageKey(), message);
              +171    }
              +172
              +173    public String getMessage(CommandIssuer issuer, MessageKeyProvider key) {
              +174        final MessageKey msgKey = key.getMessageKey();
              +175        String message = this.localeManager.getMessage(issuer, msgKey);
              +176        if (message == null) {
              +177            manager.log(LogLevel.ERROR, "Missing Language Key: " + msgKey.getKey());
              +178            message = "<MISSING_LANGUAGE_KEY:" + msgKey.getKey() + ">";
              +179        }
              +180        return message;
              +181    }
              +182
              +183    public String replaceI18NStrings(String message) {
              +184        if (message == null) {
              +185            return null;
              +186        }
              +187        Matcher matcher = ACFPatterns.I18N_STRING.matcher(message);
              +188        if (!matcher.find()) {
              +189            return message;
              +190        }
              +191
              +192        CommandIssuer issuer = CommandManager.getCurrentCommandIssuer();
              +193
              +194        matcher.reset();
              +195        StringBuffer sb = new StringBuffer(message.length());
              +196        while (matcher.find()) {
              +197            MessageKey key = MessageKey.of(matcher.group("key"));
              +198            matcher.appendReplacement(sb, Matcher.quoteReplacement(getMessage(issuer, key)));
              +199        }
              +200        matcher.appendTail(sb);
              +201        return sb.toString();
              +202    }
              +203
              +204    public boolean addBundleClassLoader(ClassLoader classLoader) {
              +205        return !this.registeredClassLoaders.contains(classLoader) && this.registeredClassLoaders.add(classLoader);
              +206
              +207    }
              +208}
               
               
               
              @@ -276,5 +277,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/MessageFormatter.html b/docs/acf-core/src-html/co/aikar/commands/MessageFormatter.html index 4423c743..1820dc0a 100644 --- a/docs/acf-core/src-html/co/aikar/commands/MessageFormatter.html +++ b/docs/acf-core/src-html/co/aikar/commands/MessageFormatter.html @@ -1,109 +1,110 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import java.util.ArrayList;
              -027import java.util.Arrays;
              -028import java.util.Collections;
              -029import java.util.List;
              -030import java.util.regex.Matcher;
              -031
              -032/**
              -033 * Handles formatting Messages and managing colors
              -034 * @param <FT> The platform specific color object
              -035 */
              -036public abstract class MessageFormatter <FT> {
              -037
              -038    private final List<FT> colors = new ArrayList<>();
              -039
              -040    @SafeVarargs
              -041    public MessageFormatter(FT... colors) {
              -042        this.colors.addAll(Arrays.asList(colors));
              -043
              -044    }
              -045    public FT setColor(int index, FT color) {
              -046        if (index > 0) {
              -047            index--;
              -048        } else {
              -049            index = 0;
              -050        }
              -051        if (this.colors.size() <= index) {
              -052            int needed = index - this.colors.size();
              -053            if (needed > 0) {
              -054                this.colors.addAll(Collections.nCopies(needed, null));
              -055            }
              -056            colors.add(color);
              -057            return null;
              -058        } else {
              -059            return colors.set(index, color);
              -060        }
              -061    }
              -062
              -063    public FT getColor(int index) {
              -064        if (index > 0) {
              -065            index--;
              -066        } else {
              -067            index = 0;
              -068        }
              -069        FT color = colors.get(index);
              -070        if (color == null) {
              -071            color = getDefaultColor();
              -072        }
              -073        return color;
              -074    }
              -075
              -076    public FT getDefaultColor() {
              -077        return getColor(1);
              -078    }
              -079
              -080    abstract String format(FT color, String message);
              -081
              -082    public String format(int index, String message) {
              -083        return format(getColor(index), message);
              -084    }
              -085
              -086    public String format(String message) {
              -087        String def = format(1, "");
              -088        Matcher matcher = ACFPatterns.FORMATTER.matcher(message);
              -089        StringBuffer sb = new StringBuffer(message.length());
              -090        while (matcher.find()) {
              -091            Integer color = ACFUtil.parseInt(matcher.group("color"), 1);
              -092            String msg = format(color, matcher.group("msg")) + def;
              -093            matcher.appendReplacement(sb, Matcher.quoteReplacement(msg));
              -094        }
              -095        matcher.appendTail(sb);
              -096        return def + sb.toString();
              -097    }
              -098}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import java.util.ArrayList;
              +027import java.util.Arrays;
              +028import java.util.Collections;
              +029import java.util.List;
              +030import java.util.regex.Matcher;
              +031
              +032/**
              +033 * Handles formatting Messages and managing colors
              +034 * @param <FT> The platform specific color object
              +035 */
              +036public abstract class MessageFormatter <FT> {
              +037
              +038    private final List<FT> colors = new ArrayList<>();
              +039
              +040    @SafeVarargs
              +041    public MessageFormatter(FT... colors) {
              +042        this.colors.addAll(Arrays.asList(colors));
              +043
              +044    }
              +045    public FT setColor(int index, FT color) {
              +046        if (index > 0) {
              +047            index--;
              +048        } else {
              +049            index = 0;
              +050        }
              +051        if (this.colors.size() <= index) {
              +052            int needed = index - this.colors.size();
              +053            if (needed > 0) {
              +054                this.colors.addAll(Collections.nCopies(needed, null));
              +055            }
              +056            colors.add(color);
              +057            return null;
              +058        } else {
              +059            return colors.set(index, color);
              +060        }
              +061    }
              +062
              +063    public FT getColor(int index) {
              +064        if (index > 0) {
              +065            index--;
              +066        } else {
              +067            index = 0;
              +068        }
              +069        FT color = colors.get(index);
              +070        if (color == null) {
              +071            color = getDefaultColor();
              +072        }
              +073        return color;
              +074    }
              +075
              +076    public FT getDefaultColor() {
              +077        return getColor(1);
              +078    }
              +079
              +080    abstract String format(FT color, String message);
              +081
              +082    public String format(int index, String message) {
              +083        return format(getColor(index), message);
              +084    }
              +085
              +086    public String format(String message) {
              +087        String def = format(1, "");
              +088        Matcher matcher = ACFPatterns.FORMATTER.matcher(message);
              +089        StringBuffer sb = new StringBuffer(message.length());
              +090        while (matcher.find()) {
              +091            Integer color = ACFUtil.parseInt(matcher.group("color"), 1);
              +092            String msg = format(color, matcher.group("msg")) + def;
              +093            matcher.appendReplacement(sb, Matcher.quoteReplacement(msg));
              +094        }
              +095        matcher.appendTail(sb);
              +096        return def + sb.toString();
              +097    }
              +098}
               
               
               
              @@ -166,5 +167,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/MessageKeys.html b/docs/acf-core/src-html/co/aikar/commands/MessageKeys.html index b337aad8..6e6f65df 100644 --- a/docs/acf-core/src-html/co/aikar/commands/MessageKeys.html +++ b/docs/acf-core/src-html/co/aikar/commands/MessageKeys.html @@ -1,77 +1,80 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.locales.MessageKey;
              -027import co.aikar.locales.MessageKeyProvider;
              -028
              -029/**
              -030 * Enum Name = MessageKey in lowercase prefixed with acf-core.
              -031 */
              -032@SuppressWarnings("WeakerAccess")
              -033public enum MessageKeys implements MessageKeyProvider {
              -034    PERMISSION_DENIED,
              -035    PERMISSION_DENIED_PARAMETER,
              -036    ERROR_GENERIC_LOGGED,
              -037    UNKNOWN_COMMAND,
              -038    INVALID_SYNTAX,
              -039    ERROR_PREFIX,
              -040    ERROR_PERFORMING_COMMAND,
              -041    INFO_MESSAGE,
              -042    PLEASE_SPECIFY_ONE_OF,
              -043    MUST_BE_A_NUMBER,
              -044    MUST_BE_MIN_LENGTH,
              -045    MUST_BE_MAX_LENGTH,
              -046    PLEASE_SPECIFY_AT_LEAST,
              -047    PLEASE_SPECIFY_AT_MOST,
              -048    NOT_ALLOWED_ON_CONSOLE,
              -049    COULD_NOT_FIND_PLAYER,
              -050    NO_COMMAND_MATCHED_SEARCH,
              -051    HELP_PAGE_INFORMATION,
              -052    HELP_NO_RESULTS,
              -053    HELP_HEADER,
              -054    HELP_FORMAT,
              -055    HELP_DETAILED_HEADER,
              -056    HELP_DETAILED_COMMAND_FORMAT,
              -057    HELP_DETAILED_PARAMETER_FORMAT,
              -058    HELP_SEARCH_HEADER,
              -059    ;
              -060
              -061    private final MessageKey key = MessageKey.of("acf-core." + this.name().toLowerCase());
              -062
              -063    public MessageKey getMessageKey() {
              -064        return key;
              -065    }
              -066}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.locales.MessageKey;
              +027import co.aikar.locales.MessageKeyProvider;
              +028
              +029import java.util.Locale;
              +030
              +031/**
              +032 * Enum Name = MessageKey in lowercase prefixed with acf-core.
              +033 */
              +034@SuppressWarnings("WeakerAccess")
              +035public enum MessageKeys implements MessageKeyProvider {
              +036    PERMISSION_DENIED,
              +037    PERMISSION_DENIED_PARAMETER,
              +038    ERROR_GENERIC_LOGGED,
              +039    UNKNOWN_COMMAND,
              +040    INVALID_SYNTAX,
              +041    ERROR_PREFIX,
              +042    ERROR_PERFORMING_COMMAND,
              +043    INFO_MESSAGE,
              +044    PLEASE_SPECIFY_ONE_OF,
              +045    MUST_BE_A_NUMBER,
              +046    MUST_BE_MIN_LENGTH,
              +047    MUST_BE_MAX_LENGTH,
              +048    PLEASE_SPECIFY_AT_LEAST,
              +049    PLEASE_SPECIFY_AT_MOST,
              +050    NOT_ALLOWED_ON_CONSOLE,
              +051    COULD_NOT_FIND_PLAYER,
              +052    NO_COMMAND_MATCHED_SEARCH,
              +053    HELP_PAGE_INFORMATION,
              +054    HELP_NO_RESULTS,
              +055    HELP_HEADER,
              +056    HELP_FORMAT,
              +057    HELP_DETAILED_HEADER,
              +058    HELP_DETAILED_COMMAND_FORMAT,
              +059    HELP_DETAILED_PARAMETER_FORMAT,
              +060    HELP_SEARCH_HEADER,
              +061    ;
              +062
              +063    private final MessageKey key = MessageKey.of("acf-core." + this.name().toLowerCase(Locale.ENGLISH));
              +064
              +065    public MessageKey getMessageKey() {
              +066        return key;
              +067    }
              +068}
               
               
               
              @@ -134,5 +137,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/MessageType.html b/docs/acf-core/src-html/co/aikar/commands/MessageType.html index 3a9ef574..95fdec05 100644 --- a/docs/acf-core/src-html/co/aikar/commands/MessageType.html +++ b/docs/acf-core/src-html/co/aikar/commands/MessageType.html @@ -1,58 +1,59 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import java.util.concurrent.atomic.AtomicInteger;
              -027
              -028@SuppressWarnings("WeakerAccess")
              -029public class MessageType {
              -030    private static final AtomicInteger counter = new AtomicInteger(1);
              -031
              -032    public static final MessageType INFO = new MessageType();
              -033    public static final MessageType SYNTAX = new MessageType();
              -034    public static final MessageType ERROR = new MessageType();
              -035    public static final MessageType HELP = new MessageType();
              -036
              -037    private final int id = counter.getAndIncrement();
              -038
              -039    public int hashCode() {
              -040        return id;
              -041    }
              -042
              -043    @Override
              -044    public boolean equals(Object o) {
              -045        return (this == o);
              -046    }
              -047}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import java.util.concurrent.atomic.AtomicInteger;
              +027
              +028@SuppressWarnings("WeakerAccess")
              +029public class MessageType {
              +030    private static final AtomicInteger counter = new AtomicInteger(1);
              +031
              +032    public static final MessageType INFO = new MessageType();
              +033    public static final MessageType SYNTAX = new MessageType();
              +034    public static final MessageType ERROR = new MessageType();
              +035    public static final MessageType HELP = new MessageType();
              +036
              +037    private final int id = counter.getAndIncrement();
              +038
              +039    public int hashCode() {
              +040        return id;
              +041    }
              +042
              +043    @Override
              +044    public boolean equals(Object o) {
              +045        return (this == o);
              +046    }
              +047}
               
               
               
              @@ -115,5 +116,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/RegisteredCommand.html b/docs/acf-core/src-html/co/aikar/commands/RegisteredCommand.html index 69a286da..c50efc65 100644 --- a/docs/acf-core/src-html/co/aikar/commands/RegisteredCommand.html +++ b/docs/acf-core/src-html/co/aikar/commands/RegisteredCommand.html @@ -1,379 +1,382 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.annotation.CommandAlias;
              -027import co.aikar.commands.annotation.CommandCompletion;
              -028import co.aikar.commands.annotation.CommandPermission;
              -029import co.aikar.commands.annotation.Conditions;
              -030import co.aikar.commands.annotation.Description;
              -031import co.aikar.commands.annotation.HelpSearchTags;
              -032import co.aikar.commands.annotation.Private;
              -033import co.aikar.commands.annotation.Syntax;
              -034import co.aikar.commands.contexts.ContextResolver;
              -035import org.jetbrains.annotations.Nullable;
              -036
              -037import java.lang.annotation.Annotation;
              -038import java.lang.reflect.InvocationTargetException;
              -039import java.lang.reflect.Method;
              -040import java.lang.reflect.Parameter;
              -041import java.util.ArrayList;
              -042import java.util.Arrays;
              -043import java.util.Collection;
              -044import java.util.HashSet;
              -045import java.util.LinkedHashMap;
              -046import java.util.List;
              -047import java.util.Map;
              -048import java.util.Set;
              -049import java.util.concurrent.CompletableFuture;
              -050import java.util.concurrent.ExecutionException;
              -051import java.util.stream.Collectors;
              -052
              -053@SuppressWarnings("WeakerAccess")
              -054public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extends CommandIssuer>> {
              -055    final BaseCommand scope;
              -056    final Method method;
              -057    final CommandParameter<CEC>[] parameters;
              -058    final CommandManager manager;
              -059    final List<String> registeredSubcommands = new ArrayList<>();
              -060
              -061    String command;
              -062    String prefSubCommand;
              -063    String syntaxText;
              -064    String helpText;
              -065    String permission;
              -066    String complete;
              -067    String conditions;
              -068    public String helpSearchTags;
              -069
              -070    boolean isPrivate;
              -071
              -072    final int requiredResolvers;
              -073    final int consumeInputResolvers;
              -074    final int doesNotConsumeInputResolvers;
              -075    final int optionalResolvers;
              -076
              -077    final Set<String> permissions = new HashSet<>();
              -078
              -079    RegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) {
              -080        this.scope = scope;
              -081        this.manager = this.scope.manager;
              -082        final Annotations annotations = this.manager.getAnnotations();
              -083
              -084        if (BaseCommand.CATCHUNKNOWN.equals(prefSubCommand) || BaseCommand.DEFAULT.equals(prefSubCommand)) {
              -085            prefSubCommand = "";
              -086            command = command.trim();
              -087        }
              -088        this.command = command + (!annotations.hasAnnotation(method, CommandAlias.class, false) && !prefSubCommand.isEmpty() ? prefSubCommand : "");
              -089        this.method = method;
              -090        this.prefSubCommand = prefSubCommand;
              -091
              -092        this.permission = annotations.getAnnotationValue(method, CommandPermission.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              -093        this.complete = annotations.getAnnotationValue(method, CommandCompletion.class, Annotations.DEFAULT_EMPTY); // no replacements as it should be per-issuer
              -094        this.helpText = annotations.getAnnotationValue(method, Description.class, Annotations.REPLACEMENTS | Annotations.DEFAULT_EMPTY);
              -095        this.conditions = annotations.getAnnotationValue(method, Conditions.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              -096        this.helpSearchTags = annotations.getAnnotationValue(method, HelpSearchTags.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              -097
              -098        Parameter[] parameters = method.getParameters();
              -099        //noinspection unchecked
              -100        this.parameters = new CommandParameter[parameters.length];
              -101
              -102        this.isPrivate = annotations.hasAnnotation(method, Private.class) || annotations.getAnnotationFromClass(scope.getClass(), Private.class) != null;
              -103
              -104        int requiredResolvers = 0;
              -105        int consumeInputResolvers = 0;
              -106        int doesNotConsumeInputResolvers = 0;
              -107        int optionalResolvers = 0;
              -108        StringBuilder syntaxBuilder = new StringBuilder(64);
              -109
              -110        for (int i = 0; i < parameters.length; i++) {
              -111            CommandParameter<CEC> parameter = this.parameters[i] = new CommandParameter<>(this, parameters[i], i, i == parameters.length - 1);
              -112            if (!parameter.isCommandIssuer()) {
              -113                if (!parameter.requiresInput()) {
              -114                    optionalResolvers++;
              -115                } else {
              -116                    requiredResolvers++;
              -117                }
              -118                if (parameter.canConsumeInput()) {
              -119                    consumeInputResolvers++;
              -120                } else {
              -121                    doesNotConsumeInputResolvers++;
              -122                }
              -123            }
              -124            if (parameter.getSyntax() != null) {
              -125                if (syntaxBuilder.length() > 0) {
              -126                    syntaxBuilder.append(' ');
              -127                }
              -128                syntaxBuilder.append(parameter.getSyntax());
              -129            }
              -130        }
              -131        String syntaxText = syntaxBuilder.toString().trim();
              -132        final String syntaxStr = annotations.getAnnotationValue(method, Syntax.class);
              -133        this.syntaxText = syntaxStr != null ? ACFUtil.replace(syntaxStr, "@syntax", syntaxText) : syntaxText;
              -134        this.requiredResolvers = requiredResolvers;
              -135        this.consumeInputResolvers = consumeInputResolvers;
              -136        this.doesNotConsumeInputResolvers = doesNotConsumeInputResolvers;
              -137        this.optionalResolvers = optionalResolvers;
              -138        this.computePermissions();
              -139    }
              -140
              -141
              -142    void invoke(CommandIssuer sender, List<String> args, CommandOperationContext context) {
              -143        if (!scope.canExecute(sender, this)) {
              -144            return;
              -145        }
              -146        preCommand();
              -147        try {
              -148            this.manager.getCommandConditions().validateConditions(context);
              -149            Map<String, Object> passedArgs = resolveContexts(sender, args);
              -150            if (passedArgs == null) return;
              -151
              -152            Object obj = method.invoke(scope, passedArgs.values().toArray());
              -153            if (obj instanceof CompletableFuture) {
              -154                CompletableFuture<?> future = (CompletableFuture) obj;
              -155                future.exceptionally(t -> {
              -156                    handleException(sender, args, t);
              -157                    return null;
              -158                });
              -159            }
              -160        } catch (Exception e) {
              -161            handleException(sender, args, e);
              -162        } finally {
              -163            postCommand();
              -164        }
              -165    }
              -166
              -167    public void preCommand() {
              -168    }
              -169
              -170    public void postCommand() {
              -171    }
              -172
              -173    void handleException(CommandIssuer sender, List<String> args, Throwable e) {
              -174        while (e instanceof ExecutionException) {
              -175            e = e.getCause();
              -176        }
              -177        if (e instanceof InvocationTargetException && e.getCause() instanceof InvalidCommandArgument) {
              -178            e = e.getCause();
              -179        }
              -180        if (e instanceof ShowCommandHelp) {
              -181            ShowCommandHelp showHelp = (ShowCommandHelp) e;
              -182            CommandHelp commandHelp = manager.generateCommandHelp();
              -183            if (showHelp.search) {
              -184                commandHelp.setSearch(showHelp.searchArgs == null ? args : showHelp.searchArgs);
              -185            }
              -186            commandHelp.showHelp(sender);
              -187        } else if (e instanceof InvalidCommandArgument) {
              -188            InvalidCommandArgument invalidCommandArg = (InvalidCommandArgument) e;
              -189            if (invalidCommandArg.key != null) {
              -190                sender.sendMessage(MessageType.ERROR, invalidCommandArg.key, invalidCommandArg.replacements);
              -191            } else if (e.getMessage() != null && !e.getMessage().isEmpty()) {
              -192                sender.sendMessage(MessageType.ERROR, MessageKeys.ERROR_PREFIX, "{message}", e.getMessage());
              -193            }
              -194            if (invalidCommandArg.showSyntax) {
              -195                scope.showSyntax(sender, this);
              -196            }
              -197        } else {
              -198            try {
              -199                if (!this.manager.handleUncaughtException(scope, this, sender, args, e)) {
              -200                    sender.sendMessage(MessageType.ERROR, MessageKeys.ERROR_PERFORMING_COMMAND);
              -201                }
              -202                boolean hasExceptionHandler = this.manager.defaultExceptionHandler != null || this.scope.getExceptionHandler() != null;
              -203                if (!hasExceptionHandler || this.manager.logUnhandledExceptions) {
              -204                    this.manager.log(LogLevel.ERROR, "Exception in command: " + command + " " + ACFUtil.join(args), e);
              -205                }
              -206            } catch (Exception e2) {
              -207                this.manager.log(LogLevel.ERROR, "Exception in handleException for command: " + command + " " + ACFUtil.join(args), e);
              -208                this.manager.log(LogLevel.ERROR, "Exception triggered by exception handler:", e2);
              -209            }
              -210        }
              -211    }
              -212
              -213    @Nullable
              -214    Map<String, Object> resolveContexts(CommandIssuer sender, List<String> args) throws InvalidCommandArgument {
              -215        return resolveContexts(sender, args, parameters.length);
              -216    }
              -217
              -218    @Nullable
              -219    Map<String, Object> resolveContexts(CommandIssuer sender, List<String> args, int argLimit) throws InvalidCommandArgument {
              -220        args = new ArrayList<>(args);
              -221        String[] origArgs = args.toArray(new String[args.size()]);
              -222        Map<String, Object> passedArgs = new LinkedHashMap<>();
              -223        int remainingRequired = requiredResolvers;
              -224        CommandOperationContext opContext = CommandManager.getCurrentCommandOperationContext();
              -225        for (int i = 0; i < parameters.length && i < argLimit; i++) {
              -226            boolean isLast = i == parameters.length - 1;
              -227            boolean allowOptional = remainingRequired == 0;
              -228            final CommandParameter<CEC> parameter = parameters[i];
              -229            if (!parameter.canConsumeInput()) {
              -230                argLimit++;
              -231            }
              -232            final String parameterName = parameter.getName();
              -233            final Class<?> type = parameter.getType();
              -234            //noinspection unchecked
              -235            final ContextResolver<?, CEC> resolver = parameter.getResolver();
              -236            //noinspection unchecked
              -237            CEC context = (CEC) this.manager.createCommandContext(this, parameter, sender, args, i, passedArgs);
              -238            boolean requiresInput = parameter.requiresInput();
              -239            if (requiresInput && remainingRequired > 0) {
              -240                remainingRequired--;
              -241            }
              -242
              -243            Set<String> parameterPermissions = parameter.getRequiredPermissions();
              -244            if (args.isEmpty() && !(isLast && type == String[].class)) {
              -245                if (allowOptional && parameter.getDefaultValue() != null) {
              -246                    args.add(parameter.getDefaultValue());
              -247                } else if (allowOptional && parameter.isOptional()) {
              -248                    Object value;
              -249                    if (!parameter.isOptionalResolver() || !this.manager.hasPermission(sender, parameterPermissions)) {
              -250                       value = null;
              -251                    } else {
              -252                       value = resolver.getContext(context);
              -253                    }
              -254
              -255                    if (value == null && parameter.getClass().isPrimitive()) {
              -256                        throw new IllegalStateException("Parameter " + parameter.getName() + " is primitive and does not support Optional.");
              -257                    }
              -258                    //noinspection unchecked
              -259                    this.manager.getCommandConditions().validateConditions(context, value);
              -260                    passedArgs.put(parameterName, value);
              -261                    continue;
              -262                } else if (requiresInput) {
              -263                    scope.showSyntax(sender, this);
              -264                    return null;
              -265                }
              -266            } else {
              -267                if (!this.manager.hasPermission(sender, parameterPermissions)) {
              -268                    sender.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED_PARAMETER, "{param}", parameterName);
              -269                    throw new InvalidCommandArgument(false);
              -270                }
              -271            }
              -272
              -273            if (parameter.getValues() != null) {
              -274                String arg = !args.isEmpty() ? args.get(0) : "";
              -275
              -276                Set<String> possible = new HashSet<>();
              -277                CommandCompletions commandCompletions = this.manager.getCommandCompletions();
              -278                for (String s : parameter.getValues()) {
              -279                    if ("*".equals(s) || "@completions".equals(s)) {
              -280                        s = commandCompletions.findDefaultCompletion(this, origArgs);
              -281                    }
              -282                    //noinspection unchecked
              -283                    List<String> check = commandCompletions.getCompletionValues(this, sender, s, origArgs, opContext.isAsync());
              -284                    if (!check.isEmpty()) {
              -285                        possible.addAll(check.stream().map(String::toLowerCase).collect(Collectors.toList()));
              -286                    } else {
              -287                        possible.add(s.toLowerCase());
              -288                    }
              -289                }
              -290                if (!possible.contains(arg.toLowerCase())) {
              -291                    throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF,
              -292                            "{valid}", ACFUtil.join(possible, ", "));
              -293                }
              -294            }
              -295
              -296            Object paramValue = resolver.getContext(context);
              -297
              -298            //noinspection unchecked
              -299            this.manager.getCommandConditions().validateConditions(context, paramValue);
              -300            passedArgs.put(parameterName, paramValue);
              -301        }
              -302        return passedArgs;
              -303    }
              -304
              -305    boolean hasPermission(CommandIssuer issuer) {
              -306        return this.manager.hasPermission(issuer, getRequiredPermissions());
              -307    }
              -308
              -309    /**
              -310     * @see #getRequiredPermissions()
              -311     * @deprecated
              -312     */
              -313    @Deprecated
              -314    public String getPermission() {
              -315        if (this.permission == null || this.permission.isEmpty()) {
              -316            return null;
              -317        }
              -318        return ACFPatterns.COMMA.split(this.permission)[0];
              -319    }
              -320
              -321    void computePermissions() {
              -322        this.permissions.clear();
              -323        this.permissions.addAll(this.scope.getRequiredPermissions());
              -324        if (this.permission != null && !this.permission.isEmpty()) {
              -325            this.permissions.addAll(Arrays.asList(ACFPatterns.COMMA.split(this.permission)));
              -326        }
              -327    }
              -328
              -329    public Set<String> getRequiredPermissions() {
              -330        return this.permissions;
              -331    }
              -332
              -333    public boolean requiresPermission(String permission) {
              -334        return getRequiredPermissions().contains(permission);
              -335    }
              -336
              -337    public String getPrefSubCommand() {
              -338        return prefSubCommand;
              -339    }
              -340
              -341    public String getSyntaxText() {
              -342        return syntaxText;
              -343    }
              -344
              -345    public String getHelpText() {
              -346        return helpText != null ? helpText : "";
              -347    }
              -348
              -349    public boolean isPrivate() {
              -350        return isPrivate;
              -351    }
              -352
              -353    public String getCommand() {
              -354        return command;
              -355    }
              -356
              -357    public void addSubcommand(String cmd) {
              -358        this.registeredSubcommands.add(cmd);
              -359    }
              -360
              -361    public void addSubcommands(Collection<String> cmd) {
              -362        this.registeredSubcommands.addAll(cmd);
              -363    }
              -364
              -365    public <T extends Annotation> T getAnnotation(Class<T> annotation) {
              -366        return method.getAnnotation(annotation);
              -367    }
              -368}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.annotation.CommandAlias;
              +027import co.aikar.commands.annotation.CommandCompletion;
              +028import co.aikar.commands.annotation.CommandPermission;
              +029import co.aikar.commands.annotation.Conditions;
              +030import co.aikar.commands.annotation.Description;
              +031import co.aikar.commands.annotation.HelpSearchTags;
              +032import co.aikar.commands.annotation.Private;
              +033import co.aikar.commands.annotation.Syntax;
              +034import co.aikar.commands.contexts.ContextResolver;
              +035import org.jetbrains.annotations.Nullable;
              +036
              +037import java.lang.annotation.Annotation;
              +038import java.lang.reflect.InvocationTargetException;
              +039import java.lang.reflect.Method;
              +040import java.lang.reflect.Parameter;
              +041import java.util.ArrayList;
              +042import java.util.Arrays;
              +043import java.util.Collection;
              +044import java.util.HashSet;
              +045import java.util.LinkedHashMap;
              +046import java.util.List;
              +047import java.util.Locale;
              +048import java.util.Map;
              +049import java.util.Set;
              +050import java.util.concurrent.CompletableFuture;
              +051import java.util.concurrent.CompletionException;
              +052import java.util.concurrent.ExecutionException;
              +053import java.util.stream.Collectors;
              +054
              +055@SuppressWarnings("WeakerAccess")
              +056public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extends CommandIssuer>> {
              +057    final BaseCommand scope;
              +058    final Method method;
              +059    final CommandParameter<CEC>[] parameters;
              +060    final CommandManager manager;
              +061    final List<String> registeredSubcommands = new ArrayList<>();
              +062
              +063    String command;
              +064    String prefSubCommand;
              +065    String syntaxText;
              +066    String helpText;
              +067    String permission;
              +068    String complete;
              +069    String conditions;
              +070    public String helpSearchTags;
              +071
              +072    boolean isPrivate;
              +073
              +074    final int requiredResolvers;
              +075    final int consumeInputResolvers;
              +076    final int doesNotConsumeInputResolvers;
              +077    final int optionalResolvers;
              +078
              +079    final Set<String> permissions = new HashSet<>();
              +080
              +081    RegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) {
              +082        this.scope = scope;
              +083        this.manager = this.scope.manager;
              +084        final Annotations annotations = this.manager.getAnnotations();
              +085
              +086        if (BaseCommand.CATCHUNKNOWN.equals(prefSubCommand) || BaseCommand.DEFAULT.equals(prefSubCommand)) {
              +087            prefSubCommand = "";
              +088            command = command.trim();
              +089        }
              +090        this.command = command + (!annotations.hasAnnotation(method, CommandAlias.class, false) && !prefSubCommand.isEmpty() ? prefSubCommand : "");
              +091        this.method = method;
              +092        this.prefSubCommand = prefSubCommand;
              +093
              +094        this.permission = annotations.getAnnotationValue(method, CommandPermission.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              +095        this.complete = annotations.getAnnotationValue(method, CommandCompletion.class, Annotations.DEFAULT_EMPTY); // no replacements as it should be per-issuer
              +096        this.helpText = annotations.getAnnotationValue(method, Description.class, Annotations.REPLACEMENTS | Annotations.DEFAULT_EMPTY);
              +097        this.conditions = annotations.getAnnotationValue(method, Conditions.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              +098        this.helpSearchTags = annotations.getAnnotationValue(method, HelpSearchTags.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
              +099
              +100        Parameter[] parameters = method.getParameters();
              +101        //noinspection unchecked
              +102        this.parameters = new CommandParameter[parameters.length];
              +103
              +104        this.isPrivate = annotations.hasAnnotation(method, Private.class) || annotations.getAnnotationFromClass(scope.getClass(), Private.class) != null;
              +105
              +106        int requiredResolvers = 0;
              +107        int consumeInputResolvers = 0;
              +108        int doesNotConsumeInputResolvers = 0;
              +109        int optionalResolvers = 0;
              +110        StringBuilder syntaxBuilder = new StringBuilder(64);
              +111
              +112        for (int i = 0; i < parameters.length; i++) {
              +113            CommandParameter<CEC> parameter = this.parameters[i] = new CommandParameter<>(this, parameters[i], i, i == parameters.length - 1);
              +114            if (!parameter.isCommandIssuer()) {
              +115                if (!parameter.requiresInput()) {
              +116                    optionalResolvers++;
              +117                } else {
              +118                    requiredResolvers++;
              +119                }
              +120                if (parameter.canConsumeInput()) {
              +121                    consumeInputResolvers++;
              +122                } else {
              +123                    doesNotConsumeInputResolvers++;
              +124                }
              +125            }
              +126            if (parameter.getSyntax() != null) {
              +127                if (syntaxBuilder.length() > 0) {
              +128                    syntaxBuilder.append(' ');
              +129                }
              +130                syntaxBuilder.append(parameter.getSyntax());
              +131            }
              +132        }
              +133        String syntaxText = syntaxBuilder.toString().trim();
              +134        final String syntaxStr = annotations.getAnnotationValue(method, Syntax.class);
              +135        this.syntaxText = syntaxStr != null ? ACFUtil.replace(syntaxStr, "@syntax", syntaxText) : syntaxText;
              +136        this.requiredResolvers = requiredResolvers;
              +137        this.consumeInputResolvers = consumeInputResolvers;
              +138        this.doesNotConsumeInputResolvers = doesNotConsumeInputResolvers;
              +139        this.optionalResolvers = optionalResolvers;
              +140        this.computePermissions();
              +141    }
              +142
              +143
              +144    void invoke(CommandIssuer sender, List<String> args, CommandOperationContext context) {
              +145        if (!scope.canExecute(sender, this)) {
              +146            return;
              +147        }
              +148        preCommand();
              +149        try {
              +150            this.manager.getCommandConditions().validateConditions(context);
              +151            Map<String, Object> passedArgs = resolveContexts(sender, args);
              +152            if (passedArgs == null) return;
              +153
              +154            Object obj = method.invoke(scope, passedArgs.values().toArray());
              +155            if (obj instanceof CompletableFuture) {
              +156                CompletableFuture<?> future = (CompletableFuture) obj;
              +157                future.exceptionally(t -> {
              +158                    handleException(sender, args, t);
              +159                    return null;
              +160                });
              +161            }
              +162        } catch (Exception e) {
              +163            handleException(sender, args, e);
              +164        } finally {
              +165            postCommand();
              +166        }
              +167    }
              +168
              +169    public void preCommand() {
              +170    }
              +171
              +172    public void postCommand() {
              +173    }
              +174
              +175    void handleException(CommandIssuer sender, List<String> args, Throwable e) {
              +176        while (e instanceof ExecutionException || e instanceof CompletionException) {
              +177            e = e.getCause();
              +178        }
              +179        if (e instanceof InvocationTargetException && e.getCause() instanceof InvalidCommandArgument) {
              +180            e = e.getCause();
              +181        }
              +182        if (e instanceof ShowCommandHelp) {
              +183            ShowCommandHelp showHelp = (ShowCommandHelp) e;
              +184            CommandHelp commandHelp = manager.generateCommandHelp();
              +185            if (showHelp.search) {
              +186                commandHelp.setSearch(showHelp.searchArgs == null ? args : showHelp.searchArgs);
              +187            }
              +188            commandHelp.showHelp(sender);
              +189        } else if (e instanceof InvalidCommandArgument) {
              +190            InvalidCommandArgument invalidCommandArg = (InvalidCommandArgument) e;
              +191            if (invalidCommandArg.key != null) {
              +192                sender.sendMessage(MessageType.ERROR, invalidCommandArg.key, invalidCommandArg.replacements);
              +193            } else if (e.getMessage() != null && !e.getMessage().isEmpty()) {
              +194                sender.sendMessage(MessageType.ERROR, MessageKeys.ERROR_PREFIX, "{message}", e.getMessage());
              +195            }
              +196            if (invalidCommandArg.showSyntax) {
              +197                scope.showSyntax(sender, this);
              +198            }
              +199        } else {
              +200            try {
              +201                if (!this.manager.handleUncaughtException(scope, this, sender, args, e)) {
              +202                    sender.sendMessage(MessageType.ERROR, MessageKeys.ERROR_PERFORMING_COMMAND);
              +203                }
              +204                boolean hasExceptionHandler = this.manager.defaultExceptionHandler != null || this.scope.getExceptionHandler() != null;
              +205                if (!hasExceptionHandler || this.manager.logUnhandledExceptions) {
              +206                    this.manager.log(LogLevel.ERROR, "Exception in command: " + command + " " + ACFUtil.join(args), e);
              +207                }
              +208            } catch (Exception e2) {
              +209                this.manager.log(LogLevel.ERROR, "Exception in handleException for command: " + command + " " + ACFUtil.join(args), e);
              +210                this.manager.log(LogLevel.ERROR, "Exception triggered by exception handler:", e2);
              +211            }
              +212        }
              +213    }
              +214
              +215    @Nullable
              +216    Map<String, Object> resolveContexts(CommandIssuer sender, List<String> args) throws InvalidCommandArgument {
              +217        return resolveContexts(sender, args, parameters.length);
              +218    }
              +219
              +220    @Nullable
              +221    Map<String, Object> resolveContexts(CommandIssuer sender, List<String> args, int argLimit) throws InvalidCommandArgument {
              +222        args = new ArrayList<>(args);
              +223        String[] origArgs = args.toArray(new String[args.size()]);
              +224        Map<String, Object> passedArgs = new LinkedHashMap<>();
              +225        int remainingRequired = requiredResolvers;
              +226        CommandOperationContext opContext = CommandManager.getCurrentCommandOperationContext();
              +227        for (int i = 0; i < parameters.length && i < argLimit; i++) {
              +228            boolean isLast = i == parameters.length - 1;
              +229            boolean allowOptional = remainingRequired == 0;
              +230            final CommandParameter<CEC> parameter = parameters[i];
              +231            if (!parameter.canConsumeInput()) {
              +232                argLimit++;
              +233            }
              +234            final String parameterName = parameter.getName();
              +235            final Class<?> type = parameter.getType();
              +236            //noinspection unchecked
              +237            final ContextResolver<?, CEC> resolver = parameter.getResolver();
              +238            //noinspection unchecked
              +239            CEC context = (CEC) this.manager.createCommandContext(this, parameter, sender, args, i, passedArgs);
              +240            boolean requiresInput = parameter.requiresInput();
              +241            if (requiresInput && remainingRequired > 0) {
              +242                remainingRequired--;
              +243            }
              +244
              +245            Set<String> parameterPermissions = parameter.getRequiredPermissions();
              +246            if (args.isEmpty() && !(isLast && type == String[].class)) {
              +247                if (allowOptional && parameter.getDefaultValue() != null) {
              +248                    args.add(parameter.getDefaultValue());
              +249                } else if (allowOptional && parameter.isOptional()) {
              +250                    Object value;
              +251                    if (!parameter.isOptionalResolver() || !this.manager.hasPermission(sender, parameterPermissions)) {
              +252                       value = null;
              +253                    } else {
              +254                       value = resolver.getContext(context);
              +255                    }
              +256
              +257                    if (value == null && parameter.getClass().isPrimitive()) {
              +258                        throw new IllegalStateException("Parameter " + parameter.getName() + " is primitive and does not support Optional.");
              +259                    }
              +260                    //noinspection unchecked
              +261                    this.manager.getCommandConditions().validateConditions(context, value);
              +262                    passedArgs.put(parameterName, value);
              +263                    continue;
              +264                } else if (requiresInput) {
              +265                    scope.showSyntax(sender, this);
              +266                    return null;
              +267                }
              +268            } else {
              +269                if (!this.manager.hasPermission(sender, parameterPermissions)) {
              +270                    sender.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED_PARAMETER, "{param}", parameterName);
              +271                    throw new InvalidCommandArgument(false);
              +272                }
              +273            }
              +274
              +275            if (parameter.getValues() != null) {
              +276                String arg = !args.isEmpty() ? args.get(0) : "";
              +277
              +278                Set<String> possible = new HashSet<>();
              +279                CommandCompletions commandCompletions = this.manager.getCommandCompletions();
              +280                for (String s : parameter.getValues()) {
              +281                    if ("*".equals(s) || "@completions".equals(s)) {
              +282                        s = commandCompletions.findDefaultCompletion(this, origArgs);
              +283                    }
              +284                    //noinspection unchecked
              +285                    List<String> check = commandCompletions.getCompletionValues(this, sender, s, origArgs, opContext.isAsync());
              +286                    if (!check.isEmpty()) {
              +287                        possible.addAll(check.stream().map(String::toLowerCase).collect(Collectors.toList()));
              +288                    } else {
              +289                        possible.add(s.toLowerCase(Locale.ENGLISH));
              +290                    }
              +291                }
              +292                if (!possible.contains(arg.toLowerCase(Locale.ENGLISH))) {
              +293                    throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF,
              +294                            "{valid}", ACFUtil.join(possible, ", "));
              +295                }
              +296            }
              +297
              +298            Object paramValue = resolver.getContext(context);
              +299
              +300            //noinspection unchecked
              +301            this.manager.getCommandConditions().validateConditions(context, paramValue);
              +302            passedArgs.put(parameterName, paramValue);
              +303        }
              +304        return passedArgs;
              +305    }
              +306
              +307    boolean hasPermission(CommandIssuer issuer) {
              +308        return this.manager.hasPermission(issuer, getRequiredPermissions());
              +309    }
              +310
              +311    /**
              +312     * @see #getRequiredPermissions()
              +313     * @deprecated
              +314     */
              +315    @Deprecated
              +316    public String getPermission() {
              +317        if (this.permission == null || this.permission.isEmpty()) {
              +318            return null;
              +319        }
              +320        return ACFPatterns.COMMA.split(this.permission)[0];
              +321    }
              +322
              +323    void computePermissions() {
              +324        this.permissions.clear();
              +325        this.permissions.addAll(this.scope.getRequiredPermissions());
              +326        if (this.permission != null && !this.permission.isEmpty()) {
              +327            this.permissions.addAll(Arrays.asList(ACFPatterns.COMMA.split(this.permission)));
              +328        }
              +329    }
              +330
              +331    public Set<String> getRequiredPermissions() {
              +332        return this.permissions;
              +333    }
              +334
              +335    public boolean requiresPermission(String permission) {
              +336        return getRequiredPermissions().contains(permission);
              +337    }
              +338
              +339    public String getPrefSubCommand() {
              +340        return prefSubCommand;
              +341    }
              +342
              +343    public String getSyntaxText() {
              +344        return syntaxText;
              +345    }
              +346
              +347    public String getHelpText() {
              +348        return helpText != null ? helpText : "";
              +349    }
              +350
              +351    public boolean isPrivate() {
              +352        return isPrivate;
              +353    }
              +354
              +355    public String getCommand() {
              +356        return command;
              +357    }
              +358
              +359    public void addSubcommand(String cmd) {
              +360        this.registeredSubcommands.add(cmd);
              +361    }
              +362
              +363    public void addSubcommands(Collection<String> cmd) {
              +364        this.registeredSubcommands.addAll(cmd);
              +365    }
              +366
              +367    public <T extends Annotation> T getAnnotation(Class<T> annotation) {
              +368        return method.getAnnotation(annotation);
              +369    }
              +370}
               
               
               
              @@ -436,5 +439,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/RootCommand.html b/docs/acf-core/src-html/co/aikar/commands/RootCommand.html index d8f595af..49beee12 100644 --- a/docs/acf-core/src-html/co/aikar/commands/RootCommand.html +++ b/docs/acf-core/src-html/co/aikar/commands/RootCommand.html @@ -1,177 +1,178 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import co.aikar.commands.CommandRouter.CommandRouteResult;
              -027import co.aikar.commands.CommandRouter.RouteSearch;
              -028import com.google.common.collect.SetMultimap;
              -029
              -030import java.util.ArrayList;
              -031import java.util.HashSet;
              -032import java.util.List;
              -033import java.util.Set;
              -034
              -035public interface RootCommand {
              -036    void addChild(BaseCommand command);
              -037
              -038    CommandManager getManager();
              -039
              -040    SetMultimap<String, RegisteredCommand> getSubCommands();
              -041
              -042    List<BaseCommand> getChildren();
              -043
              -044    String getCommandName();
              -045
              -046    default void addChildShared(List<BaseCommand> children, SetMultimap<String, RegisteredCommand> subCommands, BaseCommand command) {
              -047        command.subCommands.entries().forEach(e -> {
              -048            subCommands.put(e.getKey(), e.getValue());
              -049        });
              -050
              -051        children.add(command);
              -052    }
              -053
              -054    /**
              -055     * @return If this root command can be summarized to a single required permission node to use it, returns that value. If any RegisteredCommand is permission-less, or has multiple required permission nodes, null is returned.
              -056     */
              -057    default String getUniquePermission() {
              -058        Set<String> permissions = new HashSet<>();
              -059        for (BaseCommand child : getChildren()) {
              -060            for (RegisteredCommand<?> value : child.subCommands.values()) {
              -061                Set<String> requiredPermissions = value.getRequiredPermissions();
              -062                if (requiredPermissions.isEmpty()) {
              -063                    return null;
              -064                } else {
              -065                    permissions.addAll(requiredPermissions);
              -066                }
              -067            }
              -068        }
              -069        return permissions.size() == 1 ? permissions.iterator().next() : null;
              -070    }
              -071
              -072    default boolean hasAnyPermission(CommandIssuer issuer) {
              -073        List<BaseCommand> children = getChildren();
              -074        if (children.isEmpty()) {
              -075            return true;
              -076        }
              -077
              -078        for (BaseCommand child : children) {
              -079            if (!child.hasPermission(issuer)) {
              -080                continue;
              -081            }
              -082            for (RegisteredCommand value : child.getRegisteredCommands()) {
              -083                if (value.hasPermission(issuer)) {
              -084                    return true;
              -085                }
              -086            }
              -087        }
              -088        return false;
              -089    }
              -090
              -091    default BaseCommand execute(CommandIssuer sender, String commandLabel, String[] args) {
              -092        CommandRouter router = getManager().getRouter();
              -093        RouteSearch search = router.routeCommand(this, commandLabel, args, false);
              -094        BaseCommand defCommand = getDefCommand();
              -095        if (search != null) {
              -096            CommandRouteResult result = router.matchCommand(search, false);
              -097            if (result != null) {
              -098                BaseCommand scope = result.cmd.scope;
              -099                scope.execute(sender, result);
              -100                return scope;
              -101            }
              -102
              -103            RegisteredCommand firstElement = ACFUtil.getFirstElement(search.commands);
              -104            if (firstElement != null) {
              -105                defCommand = firstElement.scope;
              -106            }
              -107        }
              -108
              -109        defCommand.help(sender, args);
              -110        return defCommand;
              -111    }
              -112
              -113    default List<String> getTabCompletions(CommandIssuer sender, String alias, String[] args) {
              -114        return getTabCompletions(sender, alias, args, false);
              -115    }
              -116
              -117    default List<String> getTabCompletions(CommandIssuer sender, String alias, String[] args, boolean commandsOnly) {
              -118        return getTabCompletions(sender, alias, args, commandsOnly, false);
              -119    }
              -120
              -121    default List<String> getTabCompletions(CommandIssuer sender, String alias, String[] args, boolean commandsOnly, boolean isAsync) {
              -122        Set<String> completions = new HashSet<>();
              -123        getChildren().forEach(child -> {
              -124            if (!commandsOnly) {
              -125                completions.addAll(child.tabComplete(sender, this, args, isAsync));
              -126            }
              -127            completions.addAll(child.getCommandsForCompletion(sender, args));
              -128        });
              -129        return new ArrayList<>(completions);
              -130    }
              -131
              -132
              -133    default RegisteredCommand getDefaultRegisteredCommand() {
              -134        BaseCommand defCommand = this.getDefCommand();
              -135        if (defCommand != null) {
              -136            return defCommand.getDefaultRegisteredCommand();
              -137        }
              -138        return null;
              -139    }
              -140
              -141    default BaseCommand getDefCommand() {
              -142        return null;
              -143    }
              -144
              -145
              -146    default String getDescription() {
              -147        final RegisteredCommand cmd = this.getDefaultRegisteredCommand();
              -148        if (cmd != null) {
              -149            return cmd.getHelpText();
              -150        }
              -151        BaseCommand defCommand = getDefCommand();
              -152        if (defCommand != null && defCommand.description != null) {
              -153            return defCommand.description;
              -154        }
              -155        return "";
              -156    }
              -157
              -158
              -159    default String getUsage() {
              -160        final RegisteredCommand cmd = this.getDefaultRegisteredCommand();
              -161        if (cmd != null) {
              -162            return cmd.syntaxText != null ? cmd.syntaxText : "";
              -163        }
              -164        return "";
              -165    }
              -166}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import co.aikar.commands.CommandRouter.CommandRouteResult;
              +027import co.aikar.commands.CommandRouter.RouteSearch;
              +028import com.google.common.collect.SetMultimap;
              +029
              +030import java.util.ArrayList;
              +031import java.util.HashSet;
              +032import java.util.List;
              +033import java.util.Set;
              +034
              +035public interface RootCommand {
              +036    void addChild(BaseCommand command);
              +037
              +038    CommandManager getManager();
              +039
              +040    SetMultimap<String, RegisteredCommand> getSubCommands();
              +041
              +042    List<BaseCommand> getChildren();
              +043
              +044    String getCommandName();
              +045
              +046    default void addChildShared(List<BaseCommand> children, SetMultimap<String, RegisteredCommand> subCommands, BaseCommand command) {
              +047        command.subCommands.entries().forEach(e -> {
              +048            subCommands.put(e.getKey(), e.getValue());
              +049        });
              +050
              +051        children.add(command);
              +052    }
              +053
              +054    /**
              +055     * @return If this root command can be summarized to a single required permission node to use it, returns that value. If any RegisteredCommand is permission-less, or has multiple required permission nodes, null is returned.
              +056     */
              +057    default String getUniquePermission() {
              +058        Set<String> permissions = new HashSet<>();
              +059        for (BaseCommand child : getChildren()) {
              +060            for (RegisteredCommand<?> value : child.subCommands.values()) {
              +061                Set<String> requiredPermissions = value.getRequiredPermissions();
              +062                if (requiredPermissions.isEmpty()) {
              +063                    return null;
              +064                } else {
              +065                    permissions.addAll(requiredPermissions);
              +066                }
              +067            }
              +068        }
              +069        return permissions.size() == 1 ? permissions.iterator().next() : null;
              +070    }
              +071
              +072    default boolean hasAnyPermission(CommandIssuer issuer) {
              +073        List<BaseCommand> children = getChildren();
              +074        if (children.isEmpty()) {
              +075            return true;
              +076        }
              +077
              +078        for (BaseCommand child : children) {
              +079            if (!child.hasPermission(issuer)) {
              +080                continue;
              +081            }
              +082            for (RegisteredCommand value : child.getRegisteredCommands()) {
              +083                if (value.hasPermission(issuer)) {
              +084                    return true;
              +085                }
              +086            }
              +087        }
              +088        return false;
              +089    }
              +090
              +091    default BaseCommand execute(CommandIssuer sender, String commandLabel, String[] args) {
              +092        CommandRouter router = getManager().getRouter();
              +093        RouteSearch search = router.routeCommand(this, commandLabel, args, false);
              +094        BaseCommand defCommand = getDefCommand();
              +095        if (search != null) {
              +096            CommandRouteResult result = router.matchCommand(search, false);
              +097            if (result != null) {
              +098                BaseCommand scope = result.cmd.scope;
              +099                scope.execute(sender, result);
              +100                return scope;
              +101            }
              +102
              +103            RegisteredCommand firstElement = ACFUtil.getFirstElement(search.commands);
              +104            if (firstElement != null) {
              +105                defCommand = firstElement.scope;
              +106            }
              +107        }
              +108
              +109        defCommand.help(sender, args);
              +110        return defCommand;
              +111    }
              +112
              +113    default List<String> getTabCompletions(CommandIssuer sender, String alias, String[] args) {
              +114        return getTabCompletions(sender, alias, args, false);
              +115    }
              +116
              +117    default List<String> getTabCompletions(CommandIssuer sender, String alias, String[] args, boolean commandsOnly) {
              +118        return getTabCompletions(sender, alias, args, commandsOnly, false);
              +119    }
              +120
              +121    default List<String> getTabCompletions(CommandIssuer sender, String alias, String[] args, boolean commandsOnly, boolean isAsync) {
              +122        Set<String> completions = new HashSet<>();
              +123        getChildren().forEach(child -> {
              +124            if (!commandsOnly) {
              +125                completions.addAll(child.tabComplete(sender, this, args, isAsync));
              +126            }
              +127            completions.addAll(child.getCommandsForCompletion(sender, args));
              +128        });
              +129        return new ArrayList<>(completions);
              +130    }
              +131
              +132
              +133    default RegisteredCommand getDefaultRegisteredCommand() {
              +134        BaseCommand defCommand = this.getDefCommand();
              +135        if (defCommand != null) {
              +136            return defCommand.getDefaultRegisteredCommand();
              +137        }
              +138        return null;
              +139    }
              +140
              +141    default BaseCommand getDefCommand() {
              +142        return null;
              +143    }
              +144
              +145
              +146    default String getDescription() {
              +147        final RegisteredCommand cmd = this.getDefaultRegisteredCommand();
              +148        if (cmd != null) {
              +149            return cmd.getHelpText();
              +150        }
              +151        BaseCommand defCommand = getDefCommand();
              +152        if (defCommand != null && defCommand.description != null) {
              +153            return defCommand.description;
              +154        }
              +155        return "";
              +156    }
              +157
              +158
              +159    default String getUsage() {
              +160        final RegisteredCommand cmd = this.getDefaultRegisteredCommand();
              +161        if (cmd != null) {
              +162            return cmd.syntaxText != null ? cmd.syntaxText : "";
              +163        }
              +164        return "";
              +165    }
              +166}
               
               
               
              @@ -234,5 +235,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/ShowCommandHelp.html b/docs/acf-core/src-html/co/aikar/commands/ShowCommandHelp.html index db0b81eb..11f841db 100644 --- a/docs/acf-core/src-html/co/aikar/commands/ShowCommandHelp.html +++ b/docs/acf-core/src-html/co/aikar/commands/ShowCommandHelp.html @@ -1,53 +1,57 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import java.util.ArrayList;
              -027import java.util.List;
              -028
              -029public class ShowCommandHelp extends InvalidCommandArgument {
              -030    List<String> searchArgs = null;
              -031    boolean search = false;
              -032    ShowCommandHelp() {
              -033
              -034    }
              -035    ShowCommandHelp(boolean search) {
              -036        this.search = search;
              -037    }
              -038    ShowCommandHelp(List<String> args) {
              -039        this(true);
              -040        this.searchArgs = new ArrayList<>(args);
              -041    }
              -042}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import java.util.ArrayList;
              +027import java.util.List;
              +028
              +029public class ShowCommandHelp extends InvalidCommandArgument {
              +030    List<String> searchArgs = null;
              +031    boolean search = false;
              +032
              +033    public ShowCommandHelp() {
              +034
              +035    }
              +036
              +037    public ShowCommandHelp(boolean search) {
              +038        this.search = search;
              +039    }
              +040
              +041    public ShowCommandHelp(List<String> args) {
              +042        this(true);
              +043        this.searchArgs = new ArrayList<>(args);
              +044    }
              +045}
               
               
               
              @@ -110,5 +114,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/UnresolvedDependencyException.html b/docs/acf-core/src-html/co/aikar/commands/UnresolvedDependencyException.html index 35bfb198..bd899060 100644 --- a/docs/acf-core/src-html/co/aikar/commands/UnresolvedDependencyException.html +++ b/docs/acf-core/src-html/co/aikar/commands/UnresolvedDependencyException.html @@ -1,45 +1,46 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026/**
              -027 * Thrown when a command mananger couldn't find a registered instance for a field that is marked with
              -028 * {@link co.aikar.commands.annotation.Dependency}
              -029 */
              -030public class UnresolvedDependencyException extends RuntimeException {
              -031    UnresolvedDependencyException(String message) {
              -032        super(message);
              -033    }
              -034}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026/**
              +027 * Thrown when a command mananger couldn't find a registered instance for a field that is marked with
              +028 * {@link co.aikar.commands.annotation.Dependency}
              +029 */
              +030public class UnresolvedDependencyException extends RuntimeException {
              +031    UnresolvedDependencyException(String message) {
              +032        super(message);
              +033    }
              +034}
               
               
               
              @@ -102,5 +103,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/UnstableAPI.html b/docs/acf-core/src-html/co/aikar/commands/UnstableAPI.html index 7992309d..6d56ffd2 100644 --- a/docs/acf-core/src-html/co/aikar/commands/UnstableAPI.html +++ b/docs/acf-core/src-html/co/aikar/commands/UnstableAPI.html @@ -1,42 +1,43 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands;
              -025
              -026import java.lang.annotation.Retention;
              -027import java.lang.annotation.RetentionPolicy;
              -028
              -029@Retention(RetentionPolicy.RUNTIME)
              -030@Deprecated
              -031public @interface UnstableAPI {}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands;
              +025
              +026import java.lang.annotation.Retention;
              +027import java.lang.annotation.RetentionPolicy;
              +028
              +029@Retention(RetentionPolicy.RUNTIME)
              +030@Deprecated
              +031public @interface UnstableAPI {}
               
               
               
              @@ -99,5 +100,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/CatchAll.html b/docs/acf-core/src-html/co/aikar/commands/annotation/CatchAll.html index 488f339a..32acbe9d 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/CatchAll.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/CatchAll.html @@ -1,48 +1,49 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * @deprecated Use {@link CatchUnknown instead, which is more accurately named}
              -033 */
              -034@Deprecated
              -035@Retention(RetentionPolicy.RUNTIME)
              -036@Target({ElementType.METHOD})
              -037public @interface CatchAll {}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * @deprecated Use {@link CatchUnknown instead, which is more accurately named}
              +033 */
              +034@Deprecated
              +035@Retention(RetentionPolicy.RUNTIME)
              +036@Target({ElementType.METHOD})
              +037public @interface CatchAll {}
               
               
               
              @@ -105,5 +106,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/CatchUnknown.html b/docs/acf-core/src-html/co/aikar/commands/annotation/CatchUnknown.html index 5a1e1298..ebb57b4c 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/CatchUnknown.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/CatchUnknown.html @@ -1,54 +1,55 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Defines a method that should receive any unknown command for the related root command.
              -033 *
              -034 * For example, if a BaseCommand /foo has a method with this, and /foo someunknowncommand is used
              -035 *
              -036 * If a method is tagged with this annotation, it will catch unknown commands and let you react to them.
              -037 *
              -038 * Only one instance of this annotation can be used per root command.
              -039 */
              -040@Retention(RetentionPolicy.RUNTIME)
              -041@Target({ElementType.METHOD})
              -042public @interface CatchUnknown {
              -043}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Defines a method that should receive any unknown command for the related root command.
              +033 *
              +034 * For example, if a BaseCommand /foo has a method with this, and /foo someunknowncommand is used
              +035 *
              +036 * If a method is tagged with this annotation, it will catch unknown commands and let you react to them.
              +037 *
              +038 * Only one instance of this annotation can be used per root command.
              +039 */
              +040@Retention(RetentionPolicy.RUNTIME)
              +041@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
              +042public @interface CatchUnknown {
              +043}
               
               
               
              @@ -111,5 +112,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/CommandAlias.html b/docs/acf-core/src-html/co/aikar/commands/annotation/CommandAlias.html index 5579279e..2c8447ad 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/CommandAlias.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/CommandAlias.html @@ -1,54 +1,55 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Allows to add a single or several command alias(es).
              -033 * In order to add more than one in a single go, use the syntax "alias|otheralias".
              -034 * You can register as many aliases as wanted in a single value.
              -035 *
              -036 * Used on a Class, defines the root command for all subcommands in the base command.
              -037 * Used on a method, defines a root command alias to that specific command
              -038 */
              -039@Retention(RetentionPolicy.RUNTIME)
              -040@Target({ElementType.METHOD, ElementType.TYPE})
              -041public @interface CommandAlias {
              -042    String value();
              -043}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Allows to add a single or several command alias(es).
              +033 * In order to add more than one in a single go, use the syntax "alias|otheralias".
              +034 * You can register as many aliases as wanted in a single value.
              +035 *
              +036 * Used on a Class, defines the root command for all subcommands in the base command.
              +037 * Used on a method, defines a root command alias to that specific command
              +038 */
              +039@Retention(RetentionPolicy.RUNTIME)
              +040@Target({ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
              +041public @interface CommandAlias {
              +042    String value();
              +043}
               
               
               
              @@ -111,5 +112,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/CommandCompletion.html b/docs/acf-core/src-html/co/aikar/commands/annotation/CommandCompletion.html index 9c5e08b2..27dad98d 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/CommandCompletion.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/CommandCompletion.html @@ -1,56 +1,57 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Many implementation platforms have a concept of "Tab Completions",
              -033 * where pressing tab will give suggestions on what you can input.
              -034 *
              -035 * This annotation specifies either static completion values,
              -036 * or special @codes that let you define Completion Handlers to dynamically
              -037 * populate completion values.
              -038 *
              -039 * @see {@link co.aikar.commands.CommandCompletions}
              -040 */
              -041@Retention(RetentionPolicy.RUNTIME)
              -042@Target({ElementType.METHOD})
              -043public @interface CommandCompletion {
              -044    String value();
              -045}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Many implementation platforms have a concept of "Tab Completions",
              +033 * where pressing tab will give suggestions on what you can input.
              +034 *
              +035 * This annotation specifies either static completion values,
              +036 * or special @codes that let you define Completion Handlers to dynamically
              +037 * populate completion values.
              +038 *
              +039 * @see {@link co.aikar.commands.CommandCompletions}
              +040 */
              +041@Retention(RetentionPolicy.RUNTIME)
              +042@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
              +043public @interface CommandCompletion {
              +044    String value();
              +045}
               
               
               
              @@ -113,5 +114,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/CommandPermission.html b/docs/acf-core/src-html/co/aikar/commands/annotation/CommandPermission.html index a4f456c7..a7d78f53 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/CommandPermission.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/CommandPermission.html @@ -1,51 +1,52 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Sets the permission required to perform this command.
              -033 * <p>
              -034 * Permission format will vary based on implementation platform
              -035 */
              -036@Retention(RetentionPolicy.RUNTIME)
              -037@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
              -038public @interface CommandPermission {
              -039    String value();
              -040}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Sets the permission required to perform this command.
              +033 * <p>
              +034 * Permission format will vary based on implementation platform
              +035 */
              +036@Retention(RetentionPolicy.RUNTIME)
              +037@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
              +038public @interface CommandPermission {
              +039    String value();
              +040}
               
               
               
              @@ -108,5 +109,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Conditions.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Conditions.html index 908b1ec5..9f4ee3ef 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Conditions.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Conditions.html @@ -1,54 +1,55 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Specifies conditions that must be met in order to execute this command.
              -033 *
              -034 * If used on a method or a class, will be checked before parameter context is resolved
              -035 * If used on a parameter, will be checked after the context is resolved
              -036 *
              -037 * @see {@link co.aikar.commands.CommandConditions}
              -038 */
              -039@Retention(RetentionPolicy.RUNTIME)
              -040@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
              -041public @interface Conditions {
              -042    String value();
              -043}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Specifies conditions that must be met in order to execute this command.
              +033 *
              +034 * If used on a method or a class, will be checked before parameter context is resolved
              +035 * If used on a parameter, will be checked after the context is resolved
              +036 *
              +037 * @see {@link co.aikar.commands.CommandConditions}
              +038 */
              +039@Retention(RetentionPolicy.RUNTIME)
              +040@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
              +041public @interface Conditions {
              +042    String value();
              +043}
               
               
               
              @@ -111,5 +112,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Default.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Default.html index 841880bf..7e035600 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Default.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Default.html @@ -1,50 +1,51 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * If used on a method, sets default command handler for the root command of this group
              -033 * If used on a parameter, sets the value to be used for context resolution
              -034 */
              -035@Retention(RetentionPolicy.RUNTIME)
              -036@Target({ElementType.METHOD, ElementType.PARAMETER})
              -037public @interface Default {
              -038    String value() default "";
              -039}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * If used on a method, sets default command handler for the root command of this group
              +033 * If used on a parameter, sets the value to be used for context resolution
              +034 */
              +035@Retention(RetentionPolicy.RUNTIME)
              +036@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
              +037public @interface Default {
              +038    String value() default "";
              +039}
               
               
               
              @@ -107,5 +108,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Dependency.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Dependency.html index 894d5472..faa25f21 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Dependency.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Dependency.html @@ -1,54 +1,55 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Injects a dependency into the field this is attached to.
              -033 * Any time a new dependency is registered, this will be overwritten.
              -034 */
              -035@Retention(RetentionPolicy.RUNTIME)
              -036@Target(ElementType.FIELD)
              -037public @interface Dependency {
              -038    /**
              -039     * The key that should be used to lookup the instances, defaults to \"\"
              -040     * @return the key
              -041     */
              -042    String value() default "";
              -043}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Injects a dependency into the field this is attached to.
              +033 * Any time a new dependency is registered, this will be overwritten.
              +034 */
              +035@Retention(RetentionPolicy.RUNTIME)
              +036@Target(ElementType.FIELD)
              +037public @interface Dependency {
              +038    /**
              +039     * The key that should be used to lookup the instances, defaults to \"\"
              +040     * @return the key
              +041     */
              +042    String value() default "";
              +043}
               
               
               
              @@ -111,5 +112,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Description.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Description.html index 7d208160..350aefa6 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Description.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Description.html @@ -1,50 +1,51 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Sets a description to the parameter or method this is attached to.
              -033 * This is used in the help menus.
              -034 */
              -035@Retention(RetentionPolicy.RUNTIME)
              -036@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
              -037public @interface Description {
              -038    String value();
              -039}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Sets a description to the parameter or method this is attached to.
              +033 * This is used in the help menus.
              +034 */
              +035@Retention(RetentionPolicy.RUNTIME)
              +036@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
              +037public @interface Description {
              +038    String value();
              +039}
               
               
               
              @@ -107,5 +108,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Flags.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Flags.html index 2305636e..57738608 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Flags.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Flags.html @@ -1,53 +1,54 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Provides configuration options for {@link co.aikar.commands.contexts.ContextResolver}'s to change how they resolve context.
              -033 *
              -034 * Example: Searching for a player, you might use @Flags("loose") to indicate a fuzzy match instead of an exact match.
              -035 *
              -036 * If you want to restrict if an issuer can use the command, please use {@link co.aikar.commands.CommandConditions.Condition} instead.
              -037 */
              -038@Retention(RetentionPolicy.RUNTIME)
              -039@Target({ElementType.PARAMETER})
              -040public @interface Flags {
              -041    String value();
              -042}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Provides configuration options for {@link co.aikar.commands.contexts.ContextResolver}'s to change how they resolve context.
              +033 *
              +034 * Example: Searching for a player, you might use @Flags("loose") to indicate a fuzzy match instead of an exact match.
              +035 *
              +036 * If you want to restrict if an issuer can use the command, please use {@link co.aikar.commands.CommandConditions.Condition} instead.
              +037 */
              +038@Retention(RetentionPolicy.RUNTIME)
              +039@Target({ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
              +040public @interface Flags {
              +041    String value();
              +042}
               
               
               
              @@ -110,5 +111,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/HelpCommand.html b/docs/acf-core/src-html/co/aikar/commands/annotation/HelpCommand.html index f76654b1..39818481 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/HelpCommand.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/HelpCommand.html @@ -1,56 +1,57 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * A Shortcut for specifying {@link CatchUnknown}, {@link Default} and {@link Subcommand} on a method.
              -033 * Subcommand carries the same value as this annotations value to define the list of subcommands to register for.
              -034 *
              -035 * a method marked with this annotation should also use a {@link co.aikar.commands.CommandHelp} context parameter to show help.
              -036 */
              -037@Retention(RetentionPolicy.RUNTIME)
              -038@Target({ElementType.METHOD})
              -039public @interface HelpCommand {
              -040    /**
              -041     * The value to forward to the @Subcommand annotation. Lists which subcommands to register to trigger help
              -042     * @return
              -043     */
              -044    String value() default "help|?|-help|-h|-?";
              -045}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * A Shortcut for specifying {@link CatchUnknown}, {@link Default} and {@link Subcommand} on a method.
              +033 * Subcommand carries the same value as this annotations value to define the list of subcommands to register for.
              +034 *
              +035 * a method marked with this annotation should also use a {@link co.aikar.commands.CommandHelp} context parameter to show help.
              +036 */
              +037@Retention(RetentionPolicy.RUNTIME)
              +038@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
              +039public @interface HelpCommand {
              +040    /**
              +041     * The value to forward to the @Subcommand annotation. Lists which subcommands to register to trigger help
              +042     * @return
              +043     */
              +044    String value() default "help|?|-help|-h|-?";
              +045}
               
               
               
              @@ -113,5 +114,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/HelpSearchTags.html b/docs/acf-core/src-html/co/aikar/commands/annotation/HelpSearchTags.html index e9042db1..1b94feb1 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/HelpSearchTags.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/HelpSearchTags.html @@ -1,52 +1,53 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Defines additional keywords to feed into the search help system.
              -033 *
              -034 * For example, if a specific word doesn't make sense to use in the command name or description, but should
              -035 * be used for help in discovering the correct command, then you can add it as a tag.
              -036 */
              -037@Retention(RetentionPolicy.RUNTIME)
              -038@Target({ElementType.METHOD})
              -039public @interface HelpSearchTags {
              -040    String value();
              -041}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Defines additional keywords to feed into the search help system.
              +033 *
              +034 * For example, if a specific word doesn't make sense to use in the command name or description, but should
              +035 * be used for help in discovering the correct command, then you can add it as a tag.
              +036 */
              +037@Retention(RetentionPolicy.RUNTIME)
              +038@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
              +039public @interface HelpSearchTags {
              +040    String value();
              +041}
               
               
               
              @@ -109,5 +110,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Optional.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Optional.html index 5ffd4f65..e91a1576 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Optional.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Optional.html @@ -1,52 +1,53 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Marks the parameter this is attached to as optional.
              -033 * This will set the parameter as null if it was not provided.
              -034 * <p>
              -035 * In the case the language used is Kotlin, Ceylon or any other null-enforcing JVM language,
              -036 * you will need to allow for a nullable value.
              -037 */
              -038@Retention(RetentionPolicy.RUNTIME)
              -039@Target({ElementType.PARAMETER})
              -040public @interface Optional {
              -041}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Marks the parameter this is attached to as optional.
              +033 * This will set the parameter as null if it was not provided.
              +034 * <p>
              +035 * In the case the language used is Kotlin, Ceylon or any other null-enforcing JVM language,
              +036 * you will need to allow for a nullable value.
              +037 */
              +038@Retention(RetentionPolicy.RUNTIME)
              +039@Target({ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
              +040public @interface Optional {
              +041}
               
               
               
              @@ -109,5 +110,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/PreCommand.html b/docs/acf-core/src-html/co/aikar/commands/annotation/PreCommand.html index a5149019..60d11bd6 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/PreCommand.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/PreCommand.html @@ -1,48 +1,49 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026
              -027import java.lang.annotation.ElementType;
              -028import java.lang.annotation.Retention;
              -029import java.lang.annotation.RetentionPolicy;
              -030import java.lang.annotation.Target;
              -031
              -032/**
              -033 * This runs before any other command method each time it is invoked.
              -034 */
              -035@Retention(RetentionPolicy.RUNTIME)
              -036@Target({ElementType.METHOD})
              -037public @interface PreCommand {}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026
              +027import java.lang.annotation.ElementType;
              +028import java.lang.annotation.Retention;
              +029import java.lang.annotation.RetentionPolicy;
              +030import java.lang.annotation.Target;
              +031
              +032/**
              +033 * This runs before any other command method each time it is invoked.
              +034 */
              +035@Retention(RetentionPolicy.RUNTIME)
              +036@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
              +037public @interface PreCommand {}
               
               
               
              @@ -105,5 +106,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Private.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Private.html index 8f6a7e6f..e3f33371 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Private.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Private.html @@ -1,48 +1,49 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Marks a command to not be included in stuff like tab completion and help pages
              -033 */
              -034@Retention(RetentionPolicy.RUNTIME)
              -035@Target({ElementType.METHOD, ElementType.TYPE})
              -036public @interface Private {
              -037}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Marks a command to not be included in stuff like tab completion and help pages
              +033 */
              +034@Retention(RetentionPolicy.RUNTIME)
              +035@Target({ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
              +036public @interface Private {
              +037}
               
               
               
              @@ -105,5 +106,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Single.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Single.html index 151ab4d6..c4721493 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Single.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Single.html @@ -1,47 +1,48 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Don't join remaining arguments. Used on String parameters, which normally would combine the remaining arguments
              -033 */
              -034@Retention(RetentionPolicy.RUNTIME)
              -035@Target({ElementType.PARAMETER})
              -036public @interface Single {}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Don't join remaining arguments. Used on String parameters, which normally would combine the remaining arguments
              +033 */
              +034@Retention(RetentionPolicy.RUNTIME)
              +035@Target({ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
              +036public @interface Single {}
               
               
               
              @@ -104,5 +105,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Split.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Split.html index 97254097..58f489d5 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Split.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Split.html @@ -1,51 +1,52 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026
              -027import java.lang.annotation.ElementType;
              -028import java.lang.annotation.Retention;
              -029import java.lang.annotation.RetentionPolicy;
              -030import java.lang.annotation.Target;
              -031
              -032/**
              -033 * Joins arguments into a single piece of text with the specified separator.
              -034 * For array based parameters, defines the regex pattern to split on
              -035 */
              -036@Retention(RetentionPolicy.RUNTIME)
              -037@Target({ElementType.PARAMETER})
              -038public @interface Split {
              -039    String value() default ",";
              -040}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026
              +027import java.lang.annotation.ElementType;
              +028import java.lang.annotation.Retention;
              +029import java.lang.annotation.RetentionPolicy;
              +030import java.lang.annotation.Target;
              +031
              +032/**
              +033 * Joins arguments into a single piece of text with the specified separator.
              +034 * For array based parameters, defines the regex pattern to split on
              +035 */
              +036@Retention(RetentionPolicy.RUNTIME)
              +037@Target({ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
              +038public @interface Split {
              +039    String value() default ",";
              +040}
               
               
               
              @@ -108,5 +109,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Subcommand.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Subcommand.html index 1a1273e8..173b8445 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Subcommand.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Subcommand.html @@ -1,53 +1,54 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Defines the subcommand that can be used to execute this command.
              -033 * This is appended onto the root command for the command group,
              -034 * as well as any parent command groups subcommand base.
              -035 *
              -036 * Defines the part after root command like so: "/rootcommand {@link #value()}".
              -037 */
              -038@Retention(RetentionPolicy.RUNTIME)
              -039@Target({ElementType.METHOD, ElementType.TYPE})
              -040public @interface Subcommand {
              -041    String value();
              -042}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Defines the subcommand that can be used to execute this command.
              +033 * This is appended onto the root command for the command group,
              +034 * as well as any parent command groups subcommand base.
              +035 *
              +036 * Defines the part after root command like so: "/rootcommand {@link #value()}".
              +037 */
              +038@Retention(RetentionPolicy.RUNTIME)
              +039@Target({ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
              +040public @interface Subcommand {
              +041    String value();
              +042}
               
               
               
              @@ -110,5 +111,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Syntax.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Syntax.html index 610a6fc5..9162b3e8 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Syntax.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Syntax.html @@ -1,56 +1,57 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Specifies the syntax to be used when executing this command.
              -033 * It should not include any descriptions of the arguments nor when some are allowed and when they are not.
              -034 *
              -035 * Use of this annotation is not necessary. Syntax will be automatically generated for you.
              -036 * Use this annotation to override automatic syntax
              -037 *
              -038 * Use {@link Description} together with the help menu for that purpose.
              -039 **/
              -040@Retention(RetentionPolicy.RUNTIME)
              -041@Target({ElementType.METHOD, ElementType.PARAMETER})
              -042public @interface Syntax {
              -043    String value();
              -044}
              -045
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Specifies the syntax to be used when executing this command.
              +033 * It should not include any descriptions of the arguments nor when some are allowed and when they are not.
              +034 *
              +035 * Use of this annotation is not necessary. Syntax will be automatically generated for you.
              +036 * Use this annotation to override automatic syntax
              +037 *
              +038 * Use {@link Description} together with the help menu for that purpose.
              +039 **/
              +040@Retention(RetentionPolicy.RUNTIME)
              +041@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
              +042public @interface Syntax {
              +043    String value();
              +044}
              +045
               
               
               
              @@ -113,5 +114,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/UnknownHandler.html b/docs/acf-core/src-html/co/aikar/commands/annotation/UnknownHandler.html index 83543fbd..aec89753 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/UnknownHandler.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/UnknownHandler.html @@ -1,49 +1,50 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026
              -027import java.lang.annotation.ElementType;
              -028import java.lang.annotation.Retention;
              -029import java.lang.annotation.RetentionPolicy;
              -030import java.lang.annotation.Target;
              -031
              -032/**
              -033 * @deprecated Use {@link CatchUnknown instead, which is more accurately named}
              -034 */
              -035@Deprecated
              -036@Retention(RetentionPolicy.RUNTIME)
              -037@Target({ElementType.METHOD})
              -038public @interface UnknownHandler {}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026
              +027import java.lang.annotation.ElementType;
              +028import java.lang.annotation.Retention;
              +029import java.lang.annotation.RetentionPolicy;
              +030import java.lang.annotation.Target;
              +031
              +032/**
              +033 * @deprecated Use {@link CatchUnknown instead, which is more accurately named}
              +034 */
              +035@Deprecated
              +036@Retention(RetentionPolicy.RUNTIME)
              +037@Target({ElementType.METHOD})
              +038public @interface UnknownHandler {}
               
               
               
              @@ -106,5 +107,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/annotation/Values.html b/docs/acf-core/src-html/co/aikar/commands/annotation/Values.html index 7212c35f..40775752 100644 --- a/docs/acf-core/src-html/co/aikar/commands/annotation/Values.html +++ b/docs/acf-core/src-html/co/aikar/commands/annotation/Values.html @@ -1,51 +1,52 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.annotation;
              -025
              -026import java.lang.annotation.ElementType;
              -027import java.lang.annotation.Retention;
              -028import java.lang.annotation.RetentionPolicy;
              -029import java.lang.annotation.Target;
              -030
              -031/**
              -032 * Specifies a list of values that the command input should be validated against, or else show an error.
              -033 *
              -034 * You may also use {@link CommandCompletion} handler codes here to feed dynamic values and avoid repetition.
              -035 */
              -036@Retention(RetentionPolicy.RUNTIME)
              -037@Target({ElementType.PARAMETER})
              -038public @interface Values {
              -039    String value();
              -040}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.annotation;
              +025
              +026import java.lang.annotation.ElementType;
              +027import java.lang.annotation.Retention;
              +028import java.lang.annotation.RetentionPolicy;
              +029import java.lang.annotation.Target;
              +030
              +031/**
              +032 * Specifies a list of values that the command input should be validated against, or else show an error.
              +033 *
              +034 * You may also use {@link CommandCompletion} handler codes here to feed dynamic values and avoid repetition.
              +035 */
              +036@Retention(RetentionPolicy.RUNTIME)
              +037@Target({ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
              +038public @interface Values {
              +039    String value();
              +040}
               
               
               
              @@ -108,5 +109,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.Nestable.html b/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.Nestable.html index 38092927..c6af83cc 100644 --- a/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.Nestable.html +++ b/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.Nestable.html @@ -1,1025 +1,1026 @@ - + Source code +
              -
              001/*
              -002 * Licensed to the Apache Software Foundation (ASF) under one or more
              -003 * contributor license agreements.  See the NOTICE file distributed with
              -004 * this work for additional information regarding copyright ownership.
              -005 * The ASF licenses this file to You under the Apache License, Version 2.0
              -006 * (the "License"); you may not use this file except in compliance with
              -007 * the License.  You may obtain a copy of the License at
              -008 *
              -009 *      http://www.apache.org/licenses/LICENSE-2.0
              -010 *
              -011 * Unless required by applicable law or agreed to in writing, software
              -012 * distributed under the License is distributed on an "AS IS" BASIS,
              -013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
              -014 * See the License for the specific language governing permissions and
              -015 * limitations under the License.
              -016 */
              -017package co.aikar.commands.apachecommonslang;
              -018
              -019import java.io.PrintStream;
              -020import java.io.PrintWriter;
              -021import java.io.StringWriter;
              -022import java.lang.reflect.Field;
              -023import java.lang.reflect.InvocationTargetException;
              -024import java.lang.reflect.Method;
              -025import java.sql.SQLException;
              -026import java.util.ArrayList;
              -027import java.util.Arrays;
              -028import java.util.List;
              -029import java.util.StringTokenizer;
              -030
              -031/**
              -032 * <p>Provides utilities for manipulating and examining
              -033 * <code>Throwable</code> objects.</p>
              -034 *
              -035 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
              -036 * @author Dmitri Plotnikov
              -037 * @author Stephen Colebourne
              -038 * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
              -039 * @author Pete Gieser
              -040 * @since 1.0
              -041 * @version $Id$
              -042 */
              -043public class ApacheCommonsExceptionUtil {
              -044    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
              -045
              -046    /**
              -047     * <p>Used when printing stack frames to denote the start of a
              -048     * wrapped exception.</p>
              -049     *
              -050     * <p>Package private for accessibility by test suite.</p>
              -051     */
              -052    static final String WRAPPED_MARKER = " [wrapped] ";
              -053
              -054    /**
              -055     * <p>The names of methods commonly used to access a wrapped exception.</p>
              -056     */
              -057    private static String[] CAUSE_METHOD_NAMES = {
              -058            "getCause",
              -059            "getNextException",
              -060            "getTargetException",
              -061            "getException",
              -062            "getSourceException",
              -063            "getRootCause",
              -064            "getCausedByException",
              -065            "getNested",
              -066            "getLinkedException",
              -067            "getNestedException",
              -068            "getLinkedCause",
              -069            "getThrowable",
              -070    };
              -071
              -072    /**
              -073     * <p>The Method object for Java 1.4 getCause.</p>
              -074     */
              -075    private static final Method THROWABLE_CAUSE_METHOD;
              -076
              -077    /**
              -078     * <p>The Method object for Java 1.4 initCause.</p>
              -079     */
              -080    private static final Method THROWABLE_INITCAUSE_METHOD;
              -081
              -082    static {
              -083        Method causeMethod;
              -084        try {
              -085            causeMethod = Throwable.class.getMethod("getCause", null);
              -086        } catch (Exception e) {
              -087            causeMethod = null;
              -088        }
              -089        THROWABLE_CAUSE_METHOD = causeMethod;
              -090        try {
              -091            causeMethod = Throwable.class.getMethod("initCause", Throwable.class);
              -092        } catch (Exception e) {
              -093            causeMethod = null;
              -094        }
              -095        THROWABLE_INITCAUSE_METHOD = causeMethod;
              -096    }
              -097
              -098    /**
              -099     * <p>
              -100     * Public constructor allows an instance of <code>ExceptionUtils</code> to be created, although that is not
              -101     * normally necessary.
              -102     * </p>
              -103     */
              -104    public ApacheCommonsExceptionUtil() {
              -105        super();
              -106    }
              -107
              -108    //-----------------------------------------------------------------------
              -109    /**
              -110     * <p>Adds to the list of method names used in the search for <code>Throwable</code>
              -111     * objects.</p>
              -112     *
              -113     * @param methodName  the methodName to add to the list, <code>null</code>
              -114     *  and empty strings are ignored
              -115     * @since 2.0
              -116     */
              -117    public static void addCauseMethodName(String methodName) {
              -118        if (methodName != null && !methodName.isEmpty() && !isCauseMethodName(methodName)) {
              -119            List list = getCauseMethodNameList();
              -120            if (list.add(methodName)) {
              -121                CAUSE_METHOD_NAMES = toArray(list);
              -122            }
              -123        }
              -124    }
              -125
              -126    /**
              -127     * <p>Removes from the list of method names used in the search for <code>Throwable</code>
              -128     * objects.</p>
              -129     *
              -130     * @param methodName  the methodName to remove from the list, <code>null</code>
              -131     *  and empty strings are ignored
              -132     * @since 2.1
              -133     */
              -134    public static void removeCauseMethodName(String methodName) {
              -135        if (methodName != null && !methodName.isEmpty()) {
              -136            List list = getCauseMethodNameList();
              -137            if (list.remove(methodName)) {
              -138                CAUSE_METHOD_NAMES = toArray(list);
              -139            }
              -140        }
              -141    }
              -142
              -143    /**
              -144     * <p>Sets the cause of a <code>Throwable</code> using introspection, allowing
              -145     * source code compatibility between pre-1.4 and post-1.4 Java releases.</p>
              -146     *
              -147     * <p>The typical use of this method is inside a constructor as in
              -148     * the following example:</p>
              -149     *
              -150     * <pre>
              -151     * import org.apache.commons.lang.exception.ExceptionUtils;
              -152     *
              -153     * public class MyException extends Exception {
              -154     *
              -155     *    public MyException(String msg) {
              -156     *       super(msg);
              -157     *    }
              -158     *
              -159     *    public MyException(String msg, Throwable cause) {
              -160     *       super(msg);
              -161     *       ExceptionUtils.setCause(this, cause);
              -162     *    }
              -163     * }
              -164     * </pre>
              -165     *
              -166     * @param target  the target <code>Throwable</code>
              -167     * @param cause  the <code>Throwable</code> to set in the target
              -168     * @return a <code>true</code> if the target has been modified
              -169     * @since 2.2
              -170     */
              -171    public static boolean setCause(Throwable target, Throwable cause) {
              -172        if (target == null) {
              -173            throw new IllegalArgumentException("target");
              -174        }
              -175        Object[] causeArgs = new Object[]{cause};
              -176        boolean modifiedTarget = false;
              -177        if (THROWABLE_INITCAUSE_METHOD != null) {
              -178            try {
              -179                THROWABLE_INITCAUSE_METHOD.invoke(target, causeArgs);
              -180                modifiedTarget = true;
              -181            } catch (IllegalAccessException ignored) {
              -182                // Exception ignored.
              -183            } catch (InvocationTargetException ignored) {
              -184                // Exception ignored.
              -185            }
              -186        }
              -187        try {
              -188            Method setCauseMethod = target.getClass().getMethod("setCause", Throwable.class);
              -189            setCauseMethod.invoke(target, causeArgs);
              -190            modifiedTarget = true;
              -191        } catch (NoSuchMethodException ignored) {
              -192            // Exception ignored.
              -193        } catch (IllegalAccessException ignored) {
              -194            // Exception ignored.
              -195        } catch (InvocationTargetException ignored) {
              -196            // Exception ignored.
              -197        }
              -198        return modifiedTarget;
              -199    }
              -200
              -201    /**
              -202     * Returns the given list as a <code>String[]</code>.
              -203     * @param list a list to transform.
              -204     * @return the given list as a <code>String[]</code>.
              -205     */
              -206    private static String[] toArray(List list) {
              -207        return (String[]) list.toArray(new String[list.size()]);
              -208    }
              -209
              -210    /**
              -211     * Returns {@link #CAUSE_METHOD_NAMES} as a List.
              -212     *
              -213     * @return {@link #CAUSE_METHOD_NAMES} as a List.
              -214     */
              -215    private static ArrayList getCauseMethodNameList() {
              -216        return new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));
              -217    }
              -218
              -219    /**
              -220     * <p>Tests if the list of method names used in the search for <code>Throwable</code>
              -221     * objects include the given name.</p>
              -222     *
              -223     * @param methodName  the methodName to search in the list.
              -224     * @return if the list of method names used in the search for <code>Throwable</code>
              -225     *  objects include the given name.
              -226     * @since 2.1
              -227     */
              -228    public static boolean isCauseMethodName(String methodName) {
              -229        return ApacheCommonsLangUtil.indexOf(CAUSE_METHOD_NAMES, methodName) >= 0;
              -230    }
              -231
              -232    //-----------------------------------------------------------------------
              -233    /**
              -234     * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
              -235     *
              -236     * <p>The method searches for methods with specific names that return a
              -237     * <code>Throwable</code> object. This will pick up most wrapping exceptions,
              -238     * including those from JDK 1.4, and
              -239     * The method names can be added to using {@link #addCauseMethodName(String)}.</p>
              -240     *
              -241     * <p>The default list searched for are:</p>
              -242     * <ul>
              -243     *  <li><code>getCause()</code></li>
              -244     *  <li><code>getNextException()</code></li>
              -245     *  <li><code>getTargetException()</code></li>
              -246     *  <li><code>getException()</code></li>
              -247     *  <li><code>getSourceException()</code></li>
              -248     *  <li><code>getRootCause()</code></li>
              -249     *  <li><code>getCausedByException()</code></li>
              -250     *  <li><code>getNested()</code></li>
              -251     * </ul>
              -252     *
              -253     * <p>In the absence of any such method, the object is inspected for a
              -254     * <code>detail</code> field assignable to a <code>Throwable</code>.</p>
              -255     *
              -256     * <p>If none of the above is found, returns <code>null</code>.</p>
              -257     *
              -258     * @param throwable  the throwable to introspect for a cause, may be null
              -259     * @return the cause of the <code>Throwable</code>,
              -260     *  <code>null</code> if none found or null throwable input
              -261     * @since 1.0
              -262     */
              -263    public static Throwable getCause(Throwable throwable) {
              -264        return getCause(throwable, CAUSE_METHOD_NAMES);
              -265    }
              -266
              -267    /**
              -268     * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
              -269     *
              -270     * <ol>
              -271     * <li>Try known exception types.</li>
              -272     * <li>Try the supplied array of method names.</li>
              -273     * <li>Try the field 'detail'.</li>
              -274     * </ol>
              -275     *
              -276     * <p>A <code>null</code> set of method names means use the default set.
              -277     * A <code>null</code> in the set of method names will be ignored.</p>
              -278     *
              -279     * @param throwable  the throwable to introspect for a cause, may be null
              -280     * @param methodNames  the method names, null treated as default set
              -281     * @return the cause of the <code>Throwable</code>,
              -282     *  <code>null</code> if none found or null throwable input
              -283     * @since 1.0
              -284     */
              -285    public static Throwable getCause(Throwable throwable, String[] methodNames) {
              -286        if (throwable == null) {
              -287            return null;
              -288        }
              -289        Throwable cause = getCauseUsingWellKnownTypes(throwable);
              -290        if (cause == null) {
              -291            if (methodNames == null) {
              -292                methodNames = CAUSE_METHOD_NAMES;
              -293            }
              -294            for (int i = 0; i < methodNames.length; i++) {
              -295                String methodName = methodNames[i];
              -296                if (methodName != null) {
              -297                    cause = getCauseUsingMethodName(throwable, methodName);
              -298                    if (cause != null) {
              -299                        break;
              -300                    }
              -301                }
              -302            }
              -303
              -304            if (cause == null) {
              -305                cause = getCauseUsingFieldName(throwable, "detail");
              -306            }
              -307        }
              -308        return cause;
              -309    }
              -310
              -311    /**
              -312     * <p>Introspects the <code>Throwable</code> to obtain the root cause.</p>
              -313     *
              -314     * <p>This method walks through the exception chain to the last element,
              -315     * "root" of the tree, using {@link #getCause(Throwable)}, and
              -316     * returns that exception.</p>
              -317     *
              -318     * <p>From version 2.2, this method handles recursive cause structures
              -319     * that might otherwise cause infinite loops. If the throwable parameter
              -320     * has a cause of itself, then null will be returned. If the throwable
              -321     * parameter cause chain loops, the last element in the chain before the
              -322     * loop is returned.</p>
              -323     *
              -324     * @param throwable  the throwable to get the root cause for, may be null
              -325     * @return the root cause of the <code>Throwable</code>,
              -326     *  <code>null</code> if none found or null throwable input
              -327     */
              -328    public static Throwable getRootCause(Throwable throwable) {
              -329        List list = getThrowableList(throwable);
              -330        return (list.size() < 2 ? null : (Throwable)list.get(list.size() - 1));
              -331    }
              -332
              -333    /**
              -334     * <p>Finds a <code>Throwable</code> for known types.</p>
              -335     *
              -336     * <p>Uses <code>instanceof</code> checks to examine the exception,
              -337     * looking for well known types which could contain chained or
              -338     * wrapped exceptions.</p>
              -339     *
              -340     * @param throwable  the exception to examine
              -341     * @return the wrapped exception, or <code>null</code> if not found
              -342     */
              -343    private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
              -344        if (throwable instanceof Nestable) {
              -345            return throwable.getCause();
              -346        } else if (throwable instanceof SQLException) {
              -347            return ((SQLException) throwable).getNextException();
              -348        } else if (throwable instanceof InvocationTargetException) {
              -349            return ((InvocationTargetException) throwable).getTargetException();
              -350        } else {
              -351            return null;
              -352        }
              -353    }
              -354
              -355    /**
              -356     * <p>Finds a <code>Throwable</code> by method name.</p>
              -357     *
              -358     * @param throwable  the exception to examine
              -359     * @param methodName  the name of the method to find and invoke
              -360     * @return the wrapped exception, or <code>null</code> if not found
              -361     */
              -362    private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName) {
              -363        Method method = null;
              -364        try {
              -365            method = throwable.getClass().getMethod(methodName, null);
              -366        } catch (NoSuchMethodException ignored) {
              -367            // exception ignored
              -368        } catch (SecurityException ignored) {
              -369            // exception ignored
              -370        }
              -371
              -372        if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
              -373            try {
              -374                return (Throwable) method.invoke(throwable);
              -375            } catch (IllegalAccessException ignored) {
              -376                // exception ignored
              -377            } catch (IllegalArgumentException ignored) {
              -378                // exception ignored
              -379            } catch (InvocationTargetException ignored) {
              -380                // exception ignored
              -381            }
              -382        }
              -383        return null;
              -384    }
              -385
              -386    /**
              -387     * <p>Finds a <code>Throwable</code> by field name.</p>
              -388     *
              -389     * @param throwable  the exception to examine
              -390     * @param fieldName  the name of the attribute to examine
              -391     * @return the wrapped exception, or <code>null</code> if not found
              -392     */
              -393    private static Throwable getCauseUsingFieldName(Throwable throwable, String fieldName) {
              -394        Field field = null;
              -395        try {
              -396            field = throwable.getClass().getField(fieldName);
              -397        } catch (NoSuchFieldException ignored) {
              -398            // exception ignored
              -399        } catch (SecurityException ignored) {
              -400            // exception ignored
              -401        }
              -402
              -403        if (field != null && Throwable.class.isAssignableFrom(field.getType())) {
              -404            try {
              -405                return (Throwable) field.get(throwable);
              -406            } catch (IllegalAccessException ignored) {
              -407                // exception ignored
              -408            } catch (IllegalArgumentException ignored) {
              -409                // exception ignored
              -410            }
              -411        }
              -412        return null;
              -413    }
              -414
              -415    //-----------------------------------------------------------------------
              -416    /**
              -417     * <p>Checks if the Throwable class has a <code>getCause</code> method.</p>
              -418     *
              -419     * <p>This is true for JDK 1.4 and above.</p>
              -420     *
              -421     * @return true if Throwable is nestable
              -422     * @since 2.0
              -423     */
              -424    public static boolean isThrowableNested() {
              -425        return THROWABLE_CAUSE_METHOD != null;
              -426    }
              -427
              -428    /**
              -429     * <p>Checks whether this <code>Throwable</code> class can store a cause.</p>
              -430     *
              -431     * <p>This method does <b>not</b> check whether it actually does store a cause.<p>
              -432     *
              -433     * @param throwable  the <code>Throwable</code> to examine, may be null
              -434     * @return boolean <code>true</code> if nested otherwise <code>false</code>
              -435     * @since 2.0
              -436     */
              -437    public static boolean isNestedThrowable(Throwable throwable) {
              -438        if (throwable == null) {
              -439            return false;
              -440        }
              -441
              -442        if (throwable instanceof Nestable) {
              -443            return true;
              -444        } else if (throwable instanceof SQLException) {
              -445            return true;
              -446        } else if (throwable instanceof InvocationTargetException) {
              -447            return true;
              -448        } else if (isThrowableNested()) {
              -449            return true;
              -450        }
              -451
              -452        Class cls = throwable.getClass();
              -453        for (int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++) {
              -454            try {
              -455                Method method = cls.getMethod(CAUSE_METHOD_NAMES[i], null);
              -456                if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
              -457                    return true;
              -458                }
              -459            } catch (NoSuchMethodException ignored) {
              -460                // exception ignored
              -461            } catch (SecurityException ignored) {
              -462                // exception ignored
              -463            }
              -464        }
              -465
              -466        try {
              -467            Field field = cls.getField("detail");
              -468            if (field != null) {
              -469                return true;
              -470            }
              -471        } catch (NoSuchFieldException ignored) {
              -472            // exception ignored
              -473        } catch (SecurityException ignored) {
              -474            // exception ignored
              -475        }
              -476
              -477        return false;
              -478    }
              -479
              -480    //-----------------------------------------------------------------------
              -481    /**
              -482     * <p>Counts the number of <code>Throwable</code> objects in the
              -483     * exception chain.</p>
              -484     *
              -485     * <p>A throwable without cause will return <code>1</code>.
              -486     * A throwable with one cause will return <code>2</code> and so on.
              -487     * A <code>null</code> throwable will return <code>0</code>.</p>
              -488     *
              -489     * <p>From version 2.2, this method handles recursive cause structures
              -490     * that might otherwise cause infinite loops. The cause chain is
              -491     * processed until the end is reached, or until the next item in the
              -492     * chain is already in the result set.</p>
              -493     *
              -494     * @param throwable  the throwable to inspect, may be null
              -495     * @return the count of throwables, zero if null input
              -496     */
              -497    public static int getThrowableCount(Throwable throwable) {
              -498        return getThrowableList(throwable).size();
              -499    }
              -500
              -501    /**
              -502     * <p>Returns the list of <code>Throwable</code> objects in the
              -503     * exception chain.</p>
              -504     *
              -505     * <p>A throwable without cause will return an array containing
              -506     * one element - the input throwable.
              -507     * A throwable with one cause will return an array containing
              -508     * two elements. - the input throwable and the cause throwable.
              -509     * A <code>null</code> throwable will return an array of size zero.</p>
              -510     *
              -511     * <p>From version 2.2, this method handles recursive cause structures
              -512     * that might otherwise cause infinite loops. The cause chain is
              -513     * processed until the end is reached, or until the next item in the
              -514     * chain is already in the result set.</p>
              -515     *
              -516     * @see #getThrowableList(Throwable)
              -517     * @param throwable  the throwable to inspect, may be null
              -518     * @return the array of throwables, never null
              -519     */
              -520    public static Throwable[] getThrowables(Throwable throwable) {
              -521        List list = getThrowableList(throwable);
              -522        return (Throwable[]) list.toArray(new Throwable[list.size()]);
              -523    }
              -524
              -525    /**
              -526     * <p>Returns the list of <code>Throwable</code> objects in the
              -527     * exception chain.</p>
              -528     *
              -529     * <p>A throwable without cause will return a list containing
              -530     * one element - the input throwable.
              -531     * A throwable with one cause will return a list containing
              -532     * two elements. - the input throwable and the cause throwable.
              -533     * A <code>null</code> throwable will return a list of size zero.</p>
              -534     *
              -535     * <p>This method handles recursive cause structures that might
              -536     * otherwise cause infinite loops. The cause chain is processed until
              -537     * the end is reached, or until the next item in the chain is already
              -538     * in the result set.</p>
              -539     *
              -540     * @param throwable  the throwable to inspect, may be null
              -541     * @return the list of throwables, never null
              -542     * @since Commons Lang 2.2
              -543     */
              -544    public static List getThrowableList(Throwable throwable) {
              -545        List list = new ArrayList();
              -546        while (throwable != null && list.contains(throwable) == false) {
              -547            list.add(throwable);
              -548            throwable = getCause(throwable);
              -549        }
              -550        return list;
              -551    }
              -552
              -553    //-----------------------------------------------------------------------
              -554    /**
              -555     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              -556     * that matches the specified class (exactly) in the exception chain.
              -557     * Subclasses of the specified class do not match - see
              -558     * {@link #indexOfType(Throwable, Class)} for the opposite.</p>
              -559     *
              -560     * <p>A <code>null</code> throwable returns <code>-1</code>.
              -561     * A <code>null</code> type returns <code>-1</code>.
              -562     * No match in the chain returns <code>-1</code>.</p>
              -563     *
              -564     * @param throwable  the throwable to inspect, may be null
              -565     * @param clazz  the class to search for, subclasses do not match, null returns -1
              -566     * @return the index into the throwable chain, -1 if no match or null input
              -567     */
              -568    public static int indexOfThrowable(Throwable throwable, Class clazz) {
              -569        return indexOf(throwable, clazz, 0, false);
              -570    }
              -571
              -572    /**
              -573     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              -574     * that matches the specified type in the exception chain from
              -575     * a specified index.
              -576     * Subclasses of the specified class do not match - see
              -577     * {@link #indexOfType(Throwable, Class, int)} for the opposite.</p>
              -578     *
              -579     * <p>A <code>null</code> throwable returns <code>-1</code>.
              -580     * A <code>null</code> type returns <code>-1</code>.
              -581     * No match in the chain returns <code>-1</code>.
              -582     * A negative start index is treated as zero.
              -583     * A start index greater than the number of throwables returns <code>-1</code>.</p>
              -584     *
              -585     * @param throwable  the throwable to inspect, may be null
              -586     * @param clazz  the class to search for, subclasses do not match, null returns -1
              -587     * @param fromIndex  the (zero based) index of the starting position,
              -588     *  negative treated as zero, larger than chain size returns -1
              -589     * @return the index into the throwable chain, -1 if no match or null input
              -590     */
              -591    public static int indexOfThrowable(Throwable throwable, Class clazz, int fromIndex) {
              -592        return indexOf(throwable, clazz, fromIndex, false);
              -593    }
              -594
              -595    //-----------------------------------------------------------------------
              -596    /**
              -597     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              -598     * that matches the specified class or subclass in the exception chain.
              -599     * Subclasses of the specified class do match - see
              -600     * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
              -601     *
              -602     * <p>A <code>null</code> throwable returns <code>-1</code>.
              -603     * A <code>null</code> type returns <code>-1</code>.
              -604     * No match in the chain returns <code>-1</code>.</p>
              -605     *
              -606     * @param throwable  the throwable to inspect, may be null
              -607     * @param type  the type to search for, subclasses match, null returns -1
              -608     * @return the index into the throwable chain, -1 if no match or null input
              -609     * @since 2.1
              -610     */
              -611    public static int indexOfType(Throwable throwable, Class type) {
              -612        return indexOf(throwable, type, 0, true);
              -613    }
              -614
              -615    /**
              -616     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              -617     * that matches the specified type in the exception chain from
              -618     * a specified index.
              -619     * Subclasses of the specified class do match - see
              -620     * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
              -621     *
              -622     * <p>A <code>null</code> throwable returns <code>-1</code>.
              -623     * A <code>null</code> type returns <code>-1</code>.
              -624     * No match in the chain returns <code>-1</code>.
              -625     * A negative start index is treated as zero.
              -626     * A start index greater than the number of throwables returns <code>-1</code>.</p>
              -627     *
              -628     * @param throwable  the throwable to inspect, may be null
              -629     * @param type  the type to search for, subclasses match, null returns -1
              -630     * @param fromIndex  the (zero based) index of the starting position,
              -631     *  negative treated as zero, larger than chain size returns -1
              -632     * @return the index into the throwable chain, -1 if no match or null input
              -633     * @since 2.1
              -634     */
              -635    public static int indexOfType(Throwable throwable, Class type, int fromIndex) {
              -636        return indexOf(throwable, type, fromIndex, true);
              -637    }
              -638
              -639    /**
              -640     * <p>Worker method for the <code>indexOfType</code> methods.</p>
              -641     *
              -642     * @param throwable  the throwable to inspect, may be null
              -643     * @param type  the type to search for, subclasses match, null returns -1
              -644     * @param fromIndex  the (zero based) index of the starting position,
              -645     *  negative treated as zero, larger than chain size returns -1
              -646     * @param subclass if <code>true</code>, compares with {@link Class#isAssignableFrom(Class)}, otherwise compares
              -647     * using references
              -648     * @return index of the <code>type</code> within throwables nested withing the specified <code>throwable</code>
              -649     */
              -650    private static int indexOf(Throwable throwable, Class type, int fromIndex, boolean subclass) {
              -651        if (throwable == null || type == null) {
              -652            return -1;
              -653        }
              -654        if (fromIndex < 0) {
              -655            fromIndex = 0;
              -656        }
              -657        Throwable[] throwables = getThrowables(throwable);
              -658        if (fromIndex >= throwables.length) {
              -659            return -1;
              -660        }
              -661        if (subclass) {
              -662            for (int i = fromIndex; i < throwables.length; i++) {
              -663                if (type.isAssignableFrom(throwables[i].getClass())) {
              -664                    return i;
              -665                }
              -666            }
              -667        } else {
              -668            for (int i = fromIndex; i < throwables.length; i++) {
              -669                if (type.equals(throwables[i].getClass())) {
              -670                    return i;
              -671                }
              -672            }
              -673        }
              -674        return -1;
              -675    }
              -676
              -677    /**
              -678     * <p>Removes common frames from the cause trace given the two stack traces.</p>
              -679     *
              -680     * @param causeFrames  stack trace of a cause throwable
              -681     * @param wrapperFrames  stack trace of a wrapper throwable
              -682     * @throws IllegalArgumentException if either argument is null
              -683     * @since 2.0
              -684     */
              -685    public static void removeCommonFrames(List causeFrames, List wrapperFrames) {
              -686        if (causeFrames == null || wrapperFrames == null) {
              -687            throw new IllegalArgumentException("The List must not be null");
              -688        }
              -689        int causeFrameIndex = causeFrames.size() - 1;
              -690        int wrapperFrameIndex = wrapperFrames.size() - 1;
              -691        while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
              -692            // Remove the frame from the cause trace if it is the same
              -693            // as in the wrapper trace
              -694            String causeFrame = (String) causeFrames.get(causeFrameIndex);
              -695            String wrapperFrame = (String) wrapperFrames.get(wrapperFrameIndex);
              -696            if (causeFrame.equals(wrapperFrame)) {
              -697                causeFrames.remove(causeFrameIndex);
              -698            }
              -699            causeFrameIndex--;
              -700            wrapperFrameIndex--;
              -701        }
              -702    }
              -703
              -704    //-----------------------------------------------------------------------
              -705    /**
              -706     * <p>A way to get the entire nested stack-trace of an throwable.</p>
              -707     *
              -708     * <p>The result of this method is highly dependent on the JDK version
              -709     * and whether the exceptions override printStackTrace or not.</p>
              -710     *
              -711     * @param throwable  the <code>Throwable</code> to be examined
              -712     * @return the nested stack trace, with the root cause first
              -713     * @since 2.0
              -714     */
              -715    public static String getFullStackTrace(Throwable throwable) {
              -716        StringWriter sw = new StringWriter();
              -717        PrintWriter pw = new PrintWriter(sw, true);
              -718        Throwable[] ts = getThrowables(throwable);
              -719        for (int i = 0; i < ts.length; i++) {
              -720            ts[i].printStackTrace(pw);
              -721            if (isNestedThrowable(ts[i])) {
              -722                break;
              -723            }
              -724        }
              -725        return sw.getBuffer().toString();
              -726    }
              -727
              -728    //-----------------------------------------------------------------------
              -729    /**
              -730     * <p>Gets the stack trace from a Throwable as a String.</p>
              -731     *
              -732     * <p>The result of this method vary by JDK version as this method
              -733     * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
              -734     * On JDK1.3 and earlier, the cause exception will not be shown
              -735     * unless the specified throwable alters printStackTrace.</p>
              -736     *
              -737     * @param throwable  the <code>Throwable</code> to be examined
              -738     * @return the stack trace as generated by the exception's
              -739     *  <code>printStackTrace(PrintWriter)</code> method
              -740     */
              -741    public static String getStackTrace(Throwable throwable) {
              -742        StringWriter sw = new StringWriter();
              -743        PrintWriter pw = new PrintWriter(sw, true);
              -744        throwable.printStackTrace(pw);
              -745        return sw.getBuffer().toString();
              -746    }
              -747
              -748    /**
              -749     * <p>Captures the stack trace associated with the specified
              -750     * <code>Throwable</code> object, decomposing it into a list of
              -751     * stack frames.</p>
              -752     *
              -753     * <p>The result of this method vary by JDK version as this method
              -754     * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
              -755     * On JDK1.3 and earlier, the cause exception will not be shown
              -756     * unless the specified throwable alters printStackTrace.</p>
              -757     *
              -758     * @param throwable  the <code>Throwable</code> to examine, may be null
              -759     * @return an array of strings describing each stack frame, never null
              -760     */
              -761//    public static String[] getStackFrames(Throwable throwable) {
              -762//        if (throwable == null) {
              -763//            return ArrayUtils.EMPTY_STRING_ARRAY;
              -764//        }
              -765//        return getStackFrames(getStackTrace(throwable));
              -766//    }
              -767
              -768    //-----------------------------------------------------------------------
              -769    /**
              -770     * <p>Returns an array where each element is a line from the argument.</p>
              -771     *
              -772     * <p>The end of line is determined by the value of {@link SystemUtils#LINE_SEPARATOR}.</p>
              -773     *
              -774     * <p>Functionality shared between the
              -775     * <code>getStackFrames(Throwable)</code> methods of this and the
              -776     * {@link org.apache.commons.lang.exception.NestableDelegate} classes.</p>
              -777     *
              -778     * @param stackTrace  a stack trace String
              -779     * @return an array where each element is a line from the argument
              -780     */
              -781//    static String[] getStackFrames(String stackTrace) {
              -782//        String linebreak = SystemUtils.LINE_SEPARATOR;
              -783//        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
              -784//        List list = new ArrayList();
              -785//        while (frames.hasMoreTokens()) {
              -786//            list.add(frames.nextToken());
              -787//        }
              -788//        return toArray(list);
              -789//    }
              -790
              -791    /**
              -792     * <p>Produces a <code>List</code> of stack frames - the message
              -793     * is not included. Only the trace of the specified exception is
              -794     * returned, any caused by trace is stripped.</p>
              -795     *
              -796     * <p>This works in most cases - it will only fail if the exception
              -797     * message contains a line that starts with:
              -798     * <code>&quot;&nbsp;&nbsp;&nbsp;at&quot;.</code></p>
              -799     *
              -800     * @param t is any throwable
              -801     * @return List of stack frames
              -802     */
              -803    static List getStackFrameList(Throwable t) {
              -804        String stackTrace = getStackTrace(t);
              -805        String linebreak = LINE_SEPARATOR;
              -806        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
              -807        List list = new ArrayList();
              -808        boolean traceStarted = false;
              -809        while (frames.hasMoreTokens()) {
              -810            String token = frames.nextToken();
              -811            // Determine if the line starts with <whitespace>at
              -812            int at = token.indexOf("at");
              -813            if (at != -1 && token.substring(0, at).trim().length() == 0) {
              -814                traceStarted = true;
              -815                list.add(token);
              -816            } else if (traceStarted) {
              -817                break;
              -818            }
              -819        }
              -820        return list;
              -821    }
              -822
              -823    //-----------------------------------------------------------------------
              -824    /**
              -825     * Gets a short message summarising the exception.
              -826     * <p>
              -827     * The message returned is of the form
              -828     * {ClassNameWithoutPackage}: {ThrowableMessage}
              -829     *
              -830     * @param th  the throwable to get a message for, null returns empty string
              -831     * @return the message, non-null
              -832     * @since Commons Lang 2.2
              -833     */
              -834//    public static String getMessage(Throwable th) {
              -835//        if (th == null) {
              -836//            return "";
              -837//        }
              -838//        String clsName = ClassUtils.getShortClassName(th, null);
              -839//        String msg = th.getMessage();
              -840//        return clsName + ": " + StringUtils.defaultString(msg);
              -841//    }
              -842
              -843    //-----------------------------------------------------------------------
              -844    /**
              -845     * Gets a short message summarising the root cause exception.
              -846     * <p>
              -847     * The message returned is of the form
              -848     * {ClassNameWithoutPackage}: {ThrowableMessage}
              -849     *
              -850     * @param th  the throwable to get a message for, null returns empty string
              -851     * @return the message, non-null
              -852     * @since Commons Lang 2.2
              -853     */
              -854//    public static String getRootCauseMessage(Throwable th) {
              -855//        Throwable root = ExceptionUtils.getRootCause(th);
              -856//        root = (root == null ? th : root);
              -857//        return getMessage(root);
              -858//    }
              -859
              -860    /**
              -861     * An interface to be implemented by {@link java.lang.Throwable}
              -862     * extensions which would like to be able to nest root exceptions
              -863     * inside themselves.
              -864     *
              -865     * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
              -866     * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
              -867     * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
              -868     * @author Pete Gieser
              -869     * @since 1.0
              -870     * @version $Id$
              -871     */
              -872    public interface Nestable {
              -873
              -874        /**
              -875         * Returns the reference to the exception or error that caused the
              -876         * exception implementing the <code>Nestable</code> to be thrown.
              -877         *
              -878         * @return throwable that caused the original exception
              -879         */
              -880        Throwable getCause();
              -881
              -882        /**
              -883         * Returns the error message of this and any nested
              -884         * <code>Throwable</code>.
              -885         *
              -886         * @return the error message
              -887         */
              -888        String getMessage();
              -889
              -890        /**
              -891         * Returns the error message of the <code>Throwable</code> in the chain
              -892         * of <code>Throwable</code>s at the specified index, numbered from 0.
              -893         *
              -894         * @param index the index of the <code>Throwable</code> in the chain of
              -895         * <code>Throwable</code>s
              -896         * @return the error message, or null if the <code>Throwable</code> at the
              -897         * specified index in the chain does not contain a message
              -898         * @throws IndexOutOfBoundsException if the <code>index</code> argument is
              -899         * negative or not less than the count of <code>Throwable</code>s in the
              -900         * chain
              -901         */
              -902        String getMessage(int index);
              -903
              -904        /**
              -905         * Returns the error message of this and any nested <code>Throwable</code>s
              -906         * in an array of Strings, one element for each message. Any
              -907         * <code>Throwable</code> not containing a message is represented in the
              -908         * array by a null. This has the effect of cause the length of the returned
              -909         * array to be equal to the result of the {@link #getThrowableCount()}
              -910         * operation.
              -911         *
              -912         * @return the error messages
              -913         */
              -914        String[] getMessages();
              -915
              -916        /**
              -917         * Returns the <code>Throwable</code> in the chain of
              -918         * <code>Throwable</code>s at the specified index, numbered from 0.
              -919         *
              -920         * @param index the index, numbered from 0, of the <code>Throwable</code> in
              -921         * the chain of <code>Throwable</code>s
              -922         * @return the <code>Throwable</code>
              -923         * @throws IndexOutOfBoundsException if the <code>index</code> argument is
              -924         * negative or not less than the count of <code>Throwable</code>s in the
              -925         * chain
              -926         */
              -927        Throwable getThrowable(int index);
              -928
              -929        /**
              -930         * Returns the number of nested <code>Throwable</code>s represented by
              -931         * this <code>Nestable</code>, including this <code>Nestable</code>.
              -932         *
              -933         * @return the throwable count
              -934         */
              -935        int getThrowableCount();
              -936
              -937        /**
              -938         * Returns this <code>Nestable</code> and any nested <code>Throwable</code>s
              -939         * in an array of <code>Throwable</code>s, one element for each
              -940         * <code>Throwable</code>.
              -941         *
              -942         * @return the <code>Throwable</code>s
              -943         */
              -944        Throwable[] getThrowables();
              -945
              -946        /**
              -947         * Returns the index, numbered from 0, of the first occurrence of the
              -948         * specified type, or a subclass, in the chain of <code>Throwable</code>s.
              -949         * The method returns -1 if the specified type is not found in the chain.
              -950         * <p>
              -951         * NOTE: From v2.1, we have clarified the <code>Nestable</code> interface
              -952         * such that this method matches subclasses.
              -953         * If you want to NOT match subclasses, please use
              -954         * (which is avaiable in all versions of lang).
              -955         *
              -956         * @param type  the type to find, subclasses match, null returns -1
              -957         * @return index of the first occurrence of the type in the chain, or -1 if
              -958         * the type is not found
              -959         */
              -960        int indexOfThrowable(Class type);
              -961
              -962        /**
              -963         * Returns the index, numbered from 0, of the first <code>Throwable</code>
              -964         * that matches the specified type, or a subclass, in the chain of <code>Throwable</code>s
              -965         * with an index greater than or equal to the specified index.
              -966         * The method returns -1 if the specified type is not found in the chain.
              -967         * <p>
              -968         * NOTE: From v2.1, we have clarified the <code>Nestable</code> interface
              -969         * such that this method matches subclasses.
              -970         * If you want to NOT match subclasses, please use
              -971         * (which is avaiable in all versions of lang).
              -972         *
              -973         * @param type  the type to find, subclasses match, null returns -1
              -974         * @param fromIndex the index, numbered from 0, of the starting position in
              -975         * the chain to be searched
              -976         * @return index of the first occurrence of the type in the chain, or -1 if
              -977         * the type is not found
              -978         * @throws IndexOutOfBoundsException if the <code>fromIndex</code> argument
              -979         * is negative or not less than the count of <code>Throwable</code>s in the
              -980         * chain
              -981         */
              -982        int indexOfThrowable(Class type, int fromIndex);
              -983
              -984        /**
              -985         * Prints the stack trace of this exception to the specified print
              -986         * writer.  Includes information from the exception, if any,
              -987         * which caused this exception.
              -988         *
              -989         * @param out <code>PrintWriter</code> to use for output.
              -990         */
              -991        void printStackTrace(PrintWriter out);
              -992
              -993        /**
              -994         * Prints the stack trace of this exception to the specified print
              -995         * stream.  Includes information from the exception, if any,
              -996         * which caused this exception.
              -997         *
              -998         * @param out <code>PrintStream</code> to use for output.
              -999         */
              -1000        void printStackTrace(PrintStream out);
              -1001
              -1002        /**
              -1003         * Prints the stack trace for this exception only--root cause not
              -1004         * included--using the provided writer.  Used by
              -1005         * individual stack traces to a buffer.  The implementation of
              -1006         * this method should call
              -1007         * <code>super.printStackTrace(out);</code> in most cases.
              -1008         *
              -1009         * @param out The writer to use.
              -1010         */
              -1011        void printPartialStackTrace(PrintWriter out);
              -1012
              -1013    }
              -1014}
              +
              001/*
              +002 * Licensed to the Apache Software Foundation (ASF) under one or more
              +003 * contributor license agreements.  See the NOTICE file distributed with
              +004 * this work for additional information regarding copyright ownership.
              +005 * The ASF licenses this file to You under the Apache License, Version 2.0
              +006 * (the "License"); you may not use this file except in compliance with
              +007 * the License.  You may obtain a copy of the License at
              +008 *
              +009 *      http://www.apache.org/licenses/LICENSE-2.0
              +010 *
              +011 * Unless required by applicable law or agreed to in writing, software
              +012 * distributed under the License is distributed on an "AS IS" BASIS,
              +013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
              +014 * See the License for the specific language governing permissions and
              +015 * limitations under the License.
              +016 */
              +017package co.aikar.commands.apachecommonslang;
              +018
              +019import java.io.PrintStream;
              +020import java.io.PrintWriter;
              +021import java.io.StringWriter;
              +022import java.lang.reflect.Field;
              +023import java.lang.reflect.InvocationTargetException;
              +024import java.lang.reflect.Method;
              +025import java.sql.SQLException;
              +026import java.util.ArrayList;
              +027import java.util.Arrays;
              +028import java.util.List;
              +029import java.util.StringTokenizer;
              +030
              +031/**
              +032 * <p>Provides utilities for manipulating and examining
              +033 * <code>Throwable</code> objects.</p>
              +034 *
              +035 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
              +036 * @author Dmitri Plotnikov
              +037 * @author Stephen Colebourne
              +038 * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
              +039 * @author Pete Gieser
              +040 * @since 1.0
              +041 * @version $Id$
              +042 */
              +043public class ApacheCommonsExceptionUtil {
              +044    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
              +045
              +046    /**
              +047     * <p>Used when printing stack frames to denote the start of a
              +048     * wrapped exception.</p>
              +049     *
              +050     * <p>Package private for accessibility by test suite.</p>
              +051     */
              +052    static final String WRAPPED_MARKER = " [wrapped] ";
              +053
              +054    /**
              +055     * <p>The names of methods commonly used to access a wrapped exception.</p>
              +056     */
              +057    private static String[] CAUSE_METHOD_NAMES = {
              +058            "getCause",
              +059            "getNextException",
              +060            "getTargetException",
              +061            "getException",
              +062            "getSourceException",
              +063            "getRootCause",
              +064            "getCausedByException",
              +065            "getNested",
              +066            "getLinkedException",
              +067            "getNestedException",
              +068            "getLinkedCause",
              +069            "getThrowable",
              +070    };
              +071
              +072    /**
              +073     * <p>The Method object for Java 1.4 getCause.</p>
              +074     */
              +075    private static final Method THROWABLE_CAUSE_METHOD;
              +076
              +077    /**
              +078     * <p>The Method object for Java 1.4 initCause.</p>
              +079     */
              +080    private static final Method THROWABLE_INITCAUSE_METHOD;
              +081
              +082    static {
              +083        Method causeMethod;
              +084        try {
              +085            causeMethod = Throwable.class.getMethod("getCause", null);
              +086        } catch (Exception e) {
              +087            causeMethod = null;
              +088        }
              +089        THROWABLE_CAUSE_METHOD = causeMethod;
              +090        try {
              +091            causeMethod = Throwable.class.getMethod("initCause", Throwable.class);
              +092        } catch (Exception e) {
              +093            causeMethod = null;
              +094        }
              +095        THROWABLE_INITCAUSE_METHOD = causeMethod;
              +096    }
              +097
              +098    /**
              +099     * <p>
              +100     * Public constructor allows an instance of <code>ExceptionUtils</code> to be created, although that is not
              +101     * normally necessary.
              +102     * </p>
              +103     */
              +104    public ApacheCommonsExceptionUtil() {
              +105        super();
              +106    }
              +107
              +108    //-----------------------------------------------------------------------
              +109    /**
              +110     * <p>Adds to the list of method names used in the search for <code>Throwable</code>
              +111     * objects.</p>
              +112     *
              +113     * @param methodName  the methodName to add to the list, <code>null</code>
              +114     *  and empty strings are ignored
              +115     * @since 2.0
              +116     */
              +117    public static void addCauseMethodName(String methodName) {
              +118        if (methodName != null && !methodName.isEmpty() && !isCauseMethodName(methodName)) {
              +119            List list = getCauseMethodNameList();
              +120            if (list.add(methodName)) {
              +121                CAUSE_METHOD_NAMES = toArray(list);
              +122            }
              +123        }
              +124    }
              +125
              +126    /**
              +127     * <p>Removes from the list of method names used in the search for <code>Throwable</code>
              +128     * objects.</p>
              +129     *
              +130     * @param methodName  the methodName to remove from the list, <code>null</code>
              +131     *  and empty strings are ignored
              +132     * @since 2.1
              +133     */
              +134    public static void removeCauseMethodName(String methodName) {
              +135        if (methodName != null && !methodName.isEmpty()) {
              +136            List list = getCauseMethodNameList();
              +137            if (list.remove(methodName)) {
              +138                CAUSE_METHOD_NAMES = toArray(list);
              +139            }
              +140        }
              +141    }
              +142
              +143    /**
              +144     * <p>Sets the cause of a <code>Throwable</code> using introspection, allowing
              +145     * source code compatibility between pre-1.4 and post-1.4 Java releases.</p>
              +146     *
              +147     * <p>The typical use of this method is inside a constructor as in
              +148     * the following example:</p>
              +149     *
              +150     * <pre>
              +151     * import org.apache.commons.lang.exception.ExceptionUtils;
              +152     *
              +153     * public class MyException extends Exception {
              +154     *
              +155     *    public MyException(String msg) {
              +156     *       super(msg);
              +157     *    }
              +158     *
              +159     *    public MyException(String msg, Throwable cause) {
              +160     *       super(msg);
              +161     *       ExceptionUtils.setCause(this, cause);
              +162     *    }
              +163     * }
              +164     * </pre>
              +165     *
              +166     * @param target  the target <code>Throwable</code>
              +167     * @param cause  the <code>Throwable</code> to set in the target
              +168     * @return a <code>true</code> if the target has been modified
              +169     * @since 2.2
              +170     */
              +171    public static boolean setCause(Throwable target, Throwable cause) {
              +172        if (target == null) {
              +173            throw new IllegalArgumentException("target");
              +174        }
              +175        Object[] causeArgs = new Object[]{cause};
              +176        boolean modifiedTarget = false;
              +177        if (THROWABLE_INITCAUSE_METHOD != null) {
              +178            try {
              +179                THROWABLE_INITCAUSE_METHOD.invoke(target, causeArgs);
              +180                modifiedTarget = true;
              +181            } catch (IllegalAccessException ignored) {
              +182                // Exception ignored.
              +183            } catch (InvocationTargetException ignored) {
              +184                // Exception ignored.
              +185            }
              +186        }
              +187        try {
              +188            Method setCauseMethod = target.getClass().getMethod("setCause", Throwable.class);
              +189            setCauseMethod.invoke(target, causeArgs);
              +190            modifiedTarget = true;
              +191        } catch (NoSuchMethodException ignored) {
              +192            // Exception ignored.
              +193        } catch (IllegalAccessException ignored) {
              +194            // Exception ignored.
              +195        } catch (InvocationTargetException ignored) {
              +196            // Exception ignored.
              +197        }
              +198        return modifiedTarget;
              +199    }
              +200
              +201    /**
              +202     * Returns the given list as a <code>String[]</code>.
              +203     * @param list a list to transform.
              +204     * @return the given list as a <code>String[]</code>.
              +205     */
              +206    private static String[] toArray(List list) {
              +207        return (String[]) list.toArray(new String[list.size()]);
              +208    }
              +209
              +210    /**
              +211     * Returns {@link #CAUSE_METHOD_NAMES} as a List.
              +212     *
              +213     * @return {@link #CAUSE_METHOD_NAMES} as a List.
              +214     */
              +215    private static ArrayList getCauseMethodNameList() {
              +216        return new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));
              +217    }
              +218
              +219    /**
              +220     * <p>Tests if the list of method names used in the search for <code>Throwable</code>
              +221     * objects include the given name.</p>
              +222     *
              +223     * @param methodName  the methodName to search in the list.
              +224     * @return if the list of method names used in the search for <code>Throwable</code>
              +225     *  objects include the given name.
              +226     * @since 2.1
              +227     */
              +228    public static boolean isCauseMethodName(String methodName) {
              +229        return ApacheCommonsLangUtil.indexOf(CAUSE_METHOD_NAMES, methodName) >= 0;
              +230    }
              +231
              +232    //-----------------------------------------------------------------------
              +233    /**
              +234     * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
              +235     *
              +236     * <p>The method searches for methods with specific names that return a
              +237     * <code>Throwable</code> object. This will pick up most wrapping exceptions,
              +238     * including those from JDK 1.4, and
              +239     * The method names can be added to using {@link #addCauseMethodName(String)}.</p>
              +240     *
              +241     * <p>The default list searched for are:</p>
              +242     * <ul>
              +243     *  <li><code>getCause()</code></li>
              +244     *  <li><code>getNextException()</code></li>
              +245     *  <li><code>getTargetException()</code></li>
              +246     *  <li><code>getException()</code></li>
              +247     *  <li><code>getSourceException()</code></li>
              +248     *  <li><code>getRootCause()</code></li>
              +249     *  <li><code>getCausedByException()</code></li>
              +250     *  <li><code>getNested()</code></li>
              +251     * </ul>
              +252     *
              +253     * <p>In the absence of any such method, the object is inspected for a
              +254     * <code>detail</code> field assignable to a <code>Throwable</code>.</p>
              +255     *
              +256     * <p>If none of the above is found, returns <code>null</code>.</p>
              +257     *
              +258     * @param throwable  the throwable to introspect for a cause, may be null
              +259     * @return the cause of the <code>Throwable</code>,
              +260     *  <code>null</code> if none found or null throwable input
              +261     * @since 1.0
              +262     */
              +263    public static Throwable getCause(Throwable throwable) {
              +264        return getCause(throwable, CAUSE_METHOD_NAMES);
              +265    }
              +266
              +267    /**
              +268     * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
              +269     *
              +270     * <ol>
              +271     * <li>Try known exception types.</li>
              +272     * <li>Try the supplied array of method names.</li>
              +273     * <li>Try the field 'detail'.</li>
              +274     * </ol>
              +275     *
              +276     * <p>A <code>null</code> set of method names means use the default set.
              +277     * A <code>null</code> in the set of method names will be ignored.</p>
              +278     *
              +279     * @param throwable  the throwable to introspect for a cause, may be null
              +280     * @param methodNames  the method names, null treated as default set
              +281     * @return the cause of the <code>Throwable</code>,
              +282     *  <code>null</code> if none found or null throwable input
              +283     * @since 1.0
              +284     */
              +285    public static Throwable getCause(Throwable throwable, String[] methodNames) {
              +286        if (throwable == null) {
              +287            return null;
              +288        }
              +289        Throwable cause = getCauseUsingWellKnownTypes(throwable);
              +290        if (cause == null) {
              +291            if (methodNames == null) {
              +292                methodNames = CAUSE_METHOD_NAMES;
              +293            }
              +294            for (int i = 0; i < methodNames.length; i++) {
              +295                String methodName = methodNames[i];
              +296                if (methodName != null) {
              +297                    cause = getCauseUsingMethodName(throwable, methodName);
              +298                    if (cause != null) {
              +299                        break;
              +300                    }
              +301                }
              +302            }
              +303
              +304            if (cause == null) {
              +305                cause = getCauseUsingFieldName(throwable, "detail");
              +306            }
              +307        }
              +308        return cause;
              +309    }
              +310
              +311    /**
              +312     * <p>Introspects the <code>Throwable</code> to obtain the root cause.</p>
              +313     *
              +314     * <p>This method walks through the exception chain to the last element,
              +315     * "root" of the tree, using {@link #getCause(Throwable)}, and
              +316     * returns that exception.</p>
              +317     *
              +318     * <p>From version 2.2, this method handles recursive cause structures
              +319     * that might otherwise cause infinite loops. If the throwable parameter
              +320     * has a cause of itself, then null will be returned. If the throwable
              +321     * parameter cause chain loops, the last element in the chain before the
              +322     * loop is returned.</p>
              +323     *
              +324     * @param throwable  the throwable to get the root cause for, may be null
              +325     * @return the root cause of the <code>Throwable</code>,
              +326     *  <code>null</code> if none found or null throwable input
              +327     */
              +328    public static Throwable getRootCause(Throwable throwable) {
              +329        List list = getThrowableList(throwable);
              +330        return (list.size() < 2 ? null : (Throwable)list.get(list.size() - 1));
              +331    }
              +332
              +333    /**
              +334     * <p>Finds a <code>Throwable</code> for known types.</p>
              +335     *
              +336     * <p>Uses <code>instanceof</code> checks to examine the exception,
              +337     * looking for well known types which could contain chained or
              +338     * wrapped exceptions.</p>
              +339     *
              +340     * @param throwable  the exception to examine
              +341     * @return the wrapped exception, or <code>null</code> if not found
              +342     */
              +343    private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
              +344        if (throwable instanceof Nestable) {
              +345            return throwable.getCause();
              +346        } else if (throwable instanceof SQLException) {
              +347            return ((SQLException) throwable).getNextException();
              +348        } else if (throwable instanceof InvocationTargetException) {
              +349            return ((InvocationTargetException) throwable).getTargetException();
              +350        } else {
              +351            return null;
              +352        }
              +353    }
              +354
              +355    /**
              +356     * <p>Finds a <code>Throwable</code> by method name.</p>
              +357     *
              +358     * @param throwable  the exception to examine
              +359     * @param methodName  the name of the method to find and invoke
              +360     * @return the wrapped exception, or <code>null</code> if not found
              +361     */
              +362    private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName) {
              +363        Method method = null;
              +364        try {
              +365            method = throwable.getClass().getMethod(methodName, null);
              +366        } catch (NoSuchMethodException ignored) {
              +367            // exception ignored
              +368        } catch (SecurityException ignored) {
              +369            // exception ignored
              +370        }
              +371
              +372        if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
              +373            try {
              +374                return (Throwable) method.invoke(throwable);
              +375            } catch (IllegalAccessException ignored) {
              +376                // exception ignored
              +377            } catch (IllegalArgumentException ignored) {
              +378                // exception ignored
              +379            } catch (InvocationTargetException ignored) {
              +380                // exception ignored
              +381            }
              +382        }
              +383        return null;
              +384    }
              +385
              +386    /**
              +387     * <p>Finds a <code>Throwable</code> by field name.</p>
              +388     *
              +389     * @param throwable  the exception to examine
              +390     * @param fieldName  the name of the attribute to examine
              +391     * @return the wrapped exception, or <code>null</code> if not found
              +392     */
              +393    private static Throwable getCauseUsingFieldName(Throwable throwable, String fieldName) {
              +394        Field field = null;
              +395        try {
              +396            field = throwable.getClass().getField(fieldName);
              +397        } catch (NoSuchFieldException ignored) {
              +398            // exception ignored
              +399        } catch (SecurityException ignored) {
              +400            // exception ignored
              +401        }
              +402
              +403        if (field != null && Throwable.class.isAssignableFrom(field.getType())) {
              +404            try {
              +405                return (Throwable) field.get(throwable);
              +406            } catch (IllegalAccessException ignored) {
              +407                // exception ignored
              +408            } catch (IllegalArgumentException ignored) {
              +409                // exception ignored
              +410            }
              +411        }
              +412        return null;
              +413    }
              +414
              +415    //-----------------------------------------------------------------------
              +416    /**
              +417     * <p>Checks if the Throwable class has a <code>getCause</code> method.</p>
              +418     *
              +419     * <p>This is true for JDK 1.4 and above.</p>
              +420     *
              +421     * @return true if Throwable is nestable
              +422     * @since 2.0
              +423     */
              +424    public static boolean isThrowableNested() {
              +425        return THROWABLE_CAUSE_METHOD != null;
              +426    }
              +427
              +428    /**
              +429     * <p>Checks whether this <code>Throwable</code> class can store a cause.</p>
              +430     *
              +431     * <p>This method does <b>not</b> check whether it actually does store a cause.<p>
              +432     *
              +433     * @param throwable  the <code>Throwable</code> to examine, may be null
              +434     * @return boolean <code>true</code> if nested otherwise <code>false</code>
              +435     * @since 2.0
              +436     */
              +437    public static boolean isNestedThrowable(Throwable throwable) {
              +438        if (throwable == null) {
              +439            return false;
              +440        }
              +441
              +442        if (throwable instanceof Nestable) {
              +443            return true;
              +444        } else if (throwable instanceof SQLException) {
              +445            return true;
              +446        } else if (throwable instanceof InvocationTargetException) {
              +447            return true;
              +448        } else if (isThrowableNested()) {
              +449            return true;
              +450        }
              +451
              +452        Class cls = throwable.getClass();
              +453        for (int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++) {
              +454            try {
              +455                Method method = cls.getMethod(CAUSE_METHOD_NAMES[i], null);
              +456                if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
              +457                    return true;
              +458                }
              +459            } catch (NoSuchMethodException ignored) {
              +460                // exception ignored
              +461            } catch (SecurityException ignored) {
              +462                // exception ignored
              +463            }
              +464        }
              +465
              +466        try {
              +467            Field field = cls.getField("detail");
              +468            if (field != null) {
              +469                return true;
              +470            }
              +471        } catch (NoSuchFieldException ignored) {
              +472            // exception ignored
              +473        } catch (SecurityException ignored) {
              +474            // exception ignored
              +475        }
              +476
              +477        return false;
              +478    }
              +479
              +480    //-----------------------------------------------------------------------
              +481    /**
              +482     * <p>Counts the number of <code>Throwable</code> objects in the
              +483     * exception chain.</p>
              +484     *
              +485     * <p>A throwable without cause will return <code>1</code>.
              +486     * A throwable with one cause will return <code>2</code> and so on.
              +487     * A <code>null</code> throwable will return <code>0</code>.</p>
              +488     *
              +489     * <p>From version 2.2, this method handles recursive cause structures
              +490     * that might otherwise cause infinite loops. The cause chain is
              +491     * processed until the end is reached, or until the next item in the
              +492     * chain is already in the result set.</p>
              +493     *
              +494     * @param throwable  the throwable to inspect, may be null
              +495     * @return the count of throwables, zero if null input
              +496     */
              +497    public static int getThrowableCount(Throwable throwable) {
              +498        return getThrowableList(throwable).size();
              +499    }
              +500
              +501    /**
              +502     * <p>Returns the list of <code>Throwable</code> objects in the
              +503     * exception chain.</p>
              +504     *
              +505     * <p>A throwable without cause will return an array containing
              +506     * one element - the input throwable.
              +507     * A throwable with one cause will return an array containing
              +508     * two elements. - the input throwable and the cause throwable.
              +509     * A <code>null</code> throwable will return an array of size zero.</p>
              +510     *
              +511     * <p>From version 2.2, this method handles recursive cause structures
              +512     * that might otherwise cause infinite loops. The cause chain is
              +513     * processed until the end is reached, or until the next item in the
              +514     * chain is already in the result set.</p>
              +515     *
              +516     * @see #getThrowableList(Throwable)
              +517     * @param throwable  the throwable to inspect, may be null
              +518     * @return the array of throwables, never null
              +519     */
              +520    public static Throwable[] getThrowables(Throwable throwable) {
              +521        List list = getThrowableList(throwable);
              +522        return (Throwable[]) list.toArray(new Throwable[list.size()]);
              +523    }
              +524
              +525    /**
              +526     * <p>Returns the list of <code>Throwable</code> objects in the
              +527     * exception chain.</p>
              +528     *
              +529     * <p>A throwable without cause will return a list containing
              +530     * one element - the input throwable.
              +531     * A throwable with one cause will return a list containing
              +532     * two elements. - the input throwable and the cause throwable.
              +533     * A <code>null</code> throwable will return a list of size zero.</p>
              +534     *
              +535     * <p>This method handles recursive cause structures that might
              +536     * otherwise cause infinite loops. The cause chain is processed until
              +537     * the end is reached, or until the next item in the chain is already
              +538     * in the result set.</p>
              +539     *
              +540     * @param throwable  the throwable to inspect, may be null
              +541     * @return the list of throwables, never null
              +542     * @since Commons Lang 2.2
              +543     */
              +544    public static List getThrowableList(Throwable throwable) {
              +545        List list = new ArrayList();
              +546        while (throwable != null && list.contains(throwable) == false) {
              +547            list.add(throwable);
              +548            throwable = getCause(throwable);
              +549        }
              +550        return list;
              +551    }
              +552
              +553    //-----------------------------------------------------------------------
              +554    /**
              +555     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              +556     * that matches the specified class (exactly) in the exception chain.
              +557     * Subclasses of the specified class do not match - see
              +558     * {@link #indexOfType(Throwable, Class)} for the opposite.</p>
              +559     *
              +560     * <p>A <code>null</code> throwable returns <code>-1</code>.
              +561     * A <code>null</code> type returns <code>-1</code>.
              +562     * No match in the chain returns <code>-1</code>.</p>
              +563     *
              +564     * @param throwable  the throwable to inspect, may be null
              +565     * @param clazz  the class to search for, subclasses do not match, null returns -1
              +566     * @return the index into the throwable chain, -1 if no match or null input
              +567     */
              +568    public static int indexOfThrowable(Throwable throwable, Class clazz) {
              +569        return indexOf(throwable, clazz, 0, false);
              +570    }
              +571
              +572    /**
              +573     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              +574     * that matches the specified type in the exception chain from
              +575     * a specified index.
              +576     * Subclasses of the specified class do not match - see
              +577     * {@link #indexOfType(Throwable, Class, int)} for the opposite.</p>
              +578     *
              +579     * <p>A <code>null</code> throwable returns <code>-1</code>.
              +580     * A <code>null</code> type returns <code>-1</code>.
              +581     * No match in the chain returns <code>-1</code>.
              +582     * A negative start index is treated as zero.
              +583     * A start index greater than the number of throwables returns <code>-1</code>.</p>
              +584     *
              +585     * @param throwable  the throwable to inspect, may be null
              +586     * @param clazz  the class to search for, subclasses do not match, null returns -1
              +587     * @param fromIndex  the (zero based) index of the starting position,
              +588     *  negative treated as zero, larger than chain size returns -1
              +589     * @return the index into the throwable chain, -1 if no match or null input
              +590     */
              +591    public static int indexOfThrowable(Throwable throwable, Class clazz, int fromIndex) {
              +592        return indexOf(throwable, clazz, fromIndex, false);
              +593    }
              +594
              +595    //-----------------------------------------------------------------------
              +596    /**
              +597     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              +598     * that matches the specified class or subclass in the exception chain.
              +599     * Subclasses of the specified class do match - see
              +600     * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
              +601     *
              +602     * <p>A <code>null</code> throwable returns <code>-1</code>.
              +603     * A <code>null</code> type returns <code>-1</code>.
              +604     * No match in the chain returns <code>-1</code>.</p>
              +605     *
              +606     * @param throwable  the throwable to inspect, may be null
              +607     * @param type  the type to search for, subclasses match, null returns -1
              +608     * @return the index into the throwable chain, -1 if no match or null input
              +609     * @since 2.1
              +610     */
              +611    public static int indexOfType(Throwable throwable, Class type) {
              +612        return indexOf(throwable, type, 0, true);
              +613    }
              +614
              +615    /**
              +616     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              +617     * that matches the specified type in the exception chain from
              +618     * a specified index.
              +619     * Subclasses of the specified class do match - see
              +620     * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
              +621     *
              +622     * <p>A <code>null</code> throwable returns <code>-1</code>.
              +623     * A <code>null</code> type returns <code>-1</code>.
              +624     * No match in the chain returns <code>-1</code>.
              +625     * A negative start index is treated as zero.
              +626     * A start index greater than the number of throwables returns <code>-1</code>.</p>
              +627     *
              +628     * @param throwable  the throwable to inspect, may be null
              +629     * @param type  the type to search for, subclasses match, null returns -1
              +630     * @param fromIndex  the (zero based) index of the starting position,
              +631     *  negative treated as zero, larger than chain size returns -1
              +632     * @return the index into the throwable chain, -1 if no match or null input
              +633     * @since 2.1
              +634     */
              +635    public static int indexOfType(Throwable throwable, Class type, int fromIndex) {
              +636        return indexOf(throwable, type, fromIndex, true);
              +637    }
              +638
              +639    /**
              +640     * <p>Worker method for the <code>indexOfType</code> methods.</p>
              +641     *
              +642     * @param throwable  the throwable to inspect, may be null
              +643     * @param type  the type to search for, subclasses match, null returns -1
              +644     * @param fromIndex  the (zero based) index of the starting position,
              +645     *  negative treated as zero, larger than chain size returns -1
              +646     * @param subclass if <code>true</code>, compares with {@link Class#isAssignableFrom(Class)}, otherwise compares
              +647     * using references
              +648     * @return index of the <code>type</code> within throwables nested withing the specified <code>throwable</code>
              +649     */
              +650    private static int indexOf(Throwable throwable, Class type, int fromIndex, boolean subclass) {
              +651        if (throwable == null || type == null) {
              +652            return -1;
              +653        }
              +654        if (fromIndex < 0) {
              +655            fromIndex = 0;
              +656        }
              +657        Throwable[] throwables = getThrowables(throwable);
              +658        if (fromIndex >= throwables.length) {
              +659            return -1;
              +660        }
              +661        if (subclass) {
              +662            for (int i = fromIndex; i < throwables.length; i++) {
              +663                if (type.isAssignableFrom(throwables[i].getClass())) {
              +664                    return i;
              +665                }
              +666            }
              +667        } else {
              +668            for (int i = fromIndex; i < throwables.length; i++) {
              +669                if (type.equals(throwables[i].getClass())) {
              +670                    return i;
              +671                }
              +672            }
              +673        }
              +674        return -1;
              +675    }
              +676
              +677    /**
              +678     * <p>Removes common frames from the cause trace given the two stack traces.</p>
              +679     *
              +680     * @param causeFrames  stack trace of a cause throwable
              +681     * @param wrapperFrames  stack trace of a wrapper throwable
              +682     * @throws IllegalArgumentException if either argument is null
              +683     * @since 2.0
              +684     */
              +685    public static void removeCommonFrames(List causeFrames, List wrapperFrames) {
              +686        if (causeFrames == null || wrapperFrames == null) {
              +687            throw new IllegalArgumentException("The List must not be null");
              +688        }
              +689        int causeFrameIndex = causeFrames.size() - 1;
              +690        int wrapperFrameIndex = wrapperFrames.size() - 1;
              +691        while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
              +692            // Remove the frame from the cause trace if it is the same
              +693            // as in the wrapper trace
              +694            String causeFrame = (String) causeFrames.get(causeFrameIndex);
              +695            String wrapperFrame = (String) wrapperFrames.get(wrapperFrameIndex);
              +696            if (causeFrame.equals(wrapperFrame)) {
              +697                causeFrames.remove(causeFrameIndex);
              +698            }
              +699            causeFrameIndex--;
              +700            wrapperFrameIndex--;
              +701        }
              +702    }
              +703
              +704    //-----------------------------------------------------------------------
              +705    /**
              +706     * <p>A way to get the entire nested stack-trace of an throwable.</p>
              +707     *
              +708     * <p>The result of this method is highly dependent on the JDK version
              +709     * and whether the exceptions override printStackTrace or not.</p>
              +710     *
              +711     * @param throwable  the <code>Throwable</code> to be examined
              +712     * @return the nested stack trace, with the root cause first
              +713     * @since 2.0
              +714     */
              +715    public static String getFullStackTrace(Throwable throwable) {
              +716        StringWriter sw = new StringWriter();
              +717        PrintWriter pw = new PrintWriter(sw, true);
              +718        Throwable[] ts = getThrowables(throwable);
              +719        for (int i = 0; i < ts.length; i++) {
              +720            ts[i].printStackTrace(pw);
              +721            if (isNestedThrowable(ts[i])) {
              +722                break;
              +723            }
              +724        }
              +725        return sw.getBuffer().toString();
              +726    }
              +727
              +728    //-----------------------------------------------------------------------
              +729    /**
              +730     * <p>Gets the stack trace from a Throwable as a String.</p>
              +731     *
              +732     * <p>The result of this method vary by JDK version as this method
              +733     * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
              +734     * On JDK1.3 and earlier, the cause exception will not be shown
              +735     * unless the specified throwable alters printStackTrace.</p>
              +736     *
              +737     * @param throwable  the <code>Throwable</code> to be examined
              +738     * @return the stack trace as generated by the exception's
              +739     *  <code>printStackTrace(PrintWriter)</code> method
              +740     */
              +741    public static String getStackTrace(Throwable throwable) {
              +742        StringWriter sw = new StringWriter();
              +743        PrintWriter pw = new PrintWriter(sw, true);
              +744        throwable.printStackTrace(pw);
              +745        return sw.getBuffer().toString();
              +746    }
              +747
              +748    /**
              +749     * <p>Captures the stack trace associated with the specified
              +750     * <code>Throwable</code> object, decomposing it into a list of
              +751     * stack frames.</p>
              +752     *
              +753     * <p>The result of this method vary by JDK version as this method
              +754     * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
              +755     * On JDK1.3 and earlier, the cause exception will not be shown
              +756     * unless the specified throwable alters printStackTrace.</p>
              +757     *
              +758     * @param throwable  the <code>Throwable</code> to examine, may be null
              +759     * @return an array of strings describing each stack frame, never null
              +760     */
              +761//    public static String[] getStackFrames(Throwable throwable) {
              +762//        if (throwable == null) {
              +763//            return ArrayUtils.EMPTY_STRING_ARRAY;
              +764//        }
              +765//        return getStackFrames(getStackTrace(throwable));
              +766//    }
              +767
              +768    //-----------------------------------------------------------------------
              +769    /**
              +770     * <p>Returns an array where each element is a line from the argument.</p>
              +771     *
              +772     * <p>The end of line is determined by the value of {@link SystemUtils#LINE_SEPARATOR}.</p>
              +773     *
              +774     * <p>Functionality shared between the
              +775     * <code>getStackFrames(Throwable)</code> methods of this and the
              +776     * {@link org.apache.commons.lang.exception.NestableDelegate} classes.</p>
              +777     *
              +778     * @param stackTrace  a stack trace String
              +779     * @return an array where each element is a line from the argument
              +780     */
              +781//    static String[] getStackFrames(String stackTrace) {
              +782//        String linebreak = SystemUtils.LINE_SEPARATOR;
              +783//        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
              +784//        List list = new ArrayList();
              +785//        while (frames.hasMoreTokens()) {
              +786//            list.add(frames.nextToken());
              +787//        }
              +788//        return toArray(list);
              +789//    }
              +790
              +791    /**
              +792     * <p>Produces a <code>List</code> of stack frames - the message
              +793     * is not included. Only the trace of the specified exception is
              +794     * returned, any caused by trace is stripped.</p>
              +795     *
              +796     * <p>This works in most cases - it will only fail if the exception
              +797     * message contains a line that starts with:
              +798     * <code>&quot;&nbsp;&nbsp;&nbsp;at&quot;.</code></p>
              +799     *
              +800     * @param t is any throwable
              +801     * @return List of stack frames
              +802     */
              +803    static List getStackFrameList(Throwable t) {
              +804        String stackTrace = getStackTrace(t);
              +805        String linebreak = LINE_SEPARATOR;
              +806        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
              +807        List list = new ArrayList();
              +808        boolean traceStarted = false;
              +809        while (frames.hasMoreTokens()) {
              +810            String token = frames.nextToken();
              +811            // Determine if the line starts with <whitespace>at
              +812            int at = token.indexOf("at");
              +813            if (at != -1 && token.substring(0, at).trim().length() == 0) {
              +814                traceStarted = true;
              +815                list.add(token);
              +816            } else if (traceStarted) {
              +817                break;
              +818            }
              +819        }
              +820        return list;
              +821    }
              +822
              +823    //-----------------------------------------------------------------------
              +824    /**
              +825     * Gets a short message summarising the exception.
              +826     * <p>
              +827     * The message returned is of the form
              +828     * {ClassNameWithoutPackage}: {ThrowableMessage}
              +829     *
              +830     * @param th  the throwable to get a message for, null returns empty string
              +831     * @return the message, non-null
              +832     * @since Commons Lang 2.2
              +833     */
              +834//    public static String getMessage(Throwable th) {
              +835//        if (th == null) {
              +836//            return "";
              +837//        }
              +838//        String clsName = ClassUtils.getShortClassName(th, null);
              +839//        String msg = th.getMessage();
              +840//        return clsName + ": " + StringUtils.defaultString(msg);
              +841//    }
              +842
              +843    //-----------------------------------------------------------------------
              +844    /**
              +845     * Gets a short message summarising the root cause exception.
              +846     * <p>
              +847     * The message returned is of the form
              +848     * {ClassNameWithoutPackage}: {ThrowableMessage}
              +849     *
              +850     * @param th  the throwable to get a message for, null returns empty string
              +851     * @return the message, non-null
              +852     * @since Commons Lang 2.2
              +853     */
              +854//    public static String getRootCauseMessage(Throwable th) {
              +855//        Throwable root = ExceptionUtils.getRootCause(th);
              +856//        root = (root == null ? th : root);
              +857//        return getMessage(root);
              +858//    }
              +859
              +860    /**
              +861     * An interface to be implemented by {@link java.lang.Throwable}
              +862     * extensions which would like to be able to nest root exceptions
              +863     * inside themselves.
              +864     *
              +865     * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
              +866     * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
              +867     * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
              +868     * @author Pete Gieser
              +869     * @since 1.0
              +870     * @version $Id$
              +871     */
              +872    public interface Nestable {
              +873
              +874        /**
              +875         * Returns the reference to the exception or error that caused the
              +876         * exception implementing the <code>Nestable</code> to be thrown.
              +877         *
              +878         * @return throwable that caused the original exception
              +879         */
              +880        Throwable getCause();
              +881
              +882        /**
              +883         * Returns the error message of this and any nested
              +884         * <code>Throwable</code>.
              +885         *
              +886         * @return the error message
              +887         */
              +888        String getMessage();
              +889
              +890        /**
              +891         * Returns the error message of the <code>Throwable</code> in the chain
              +892         * of <code>Throwable</code>s at the specified index, numbered from 0.
              +893         *
              +894         * @param index the index of the <code>Throwable</code> in the chain of
              +895         * <code>Throwable</code>s
              +896         * @return the error message, or null if the <code>Throwable</code> at the
              +897         * specified index in the chain does not contain a message
              +898         * @throws IndexOutOfBoundsException if the <code>index</code> argument is
              +899         * negative or not less than the count of <code>Throwable</code>s in the
              +900         * chain
              +901         */
              +902        String getMessage(int index);
              +903
              +904        /**
              +905         * Returns the error message of this and any nested <code>Throwable</code>s
              +906         * in an array of Strings, one element for each message. Any
              +907         * <code>Throwable</code> not containing a message is represented in the
              +908         * array by a null. This has the effect of cause the length of the returned
              +909         * array to be equal to the result of the {@link #getThrowableCount()}
              +910         * operation.
              +911         *
              +912         * @return the error messages
              +913         */
              +914        String[] getMessages();
              +915
              +916        /**
              +917         * Returns the <code>Throwable</code> in the chain of
              +918         * <code>Throwable</code>s at the specified index, numbered from 0.
              +919         *
              +920         * @param index the index, numbered from 0, of the <code>Throwable</code> in
              +921         * the chain of <code>Throwable</code>s
              +922         * @return the <code>Throwable</code>
              +923         * @throws IndexOutOfBoundsException if the <code>index</code> argument is
              +924         * negative or not less than the count of <code>Throwable</code>s in the
              +925         * chain
              +926         */
              +927        Throwable getThrowable(int index);
              +928
              +929        /**
              +930         * Returns the number of nested <code>Throwable</code>s represented by
              +931         * this <code>Nestable</code>, including this <code>Nestable</code>.
              +932         *
              +933         * @return the throwable count
              +934         */
              +935        int getThrowableCount();
              +936
              +937        /**
              +938         * Returns this <code>Nestable</code> and any nested <code>Throwable</code>s
              +939         * in an array of <code>Throwable</code>s, one element for each
              +940         * <code>Throwable</code>.
              +941         *
              +942         * @return the <code>Throwable</code>s
              +943         */
              +944        Throwable[] getThrowables();
              +945
              +946        /**
              +947         * Returns the index, numbered from 0, of the first occurrence of the
              +948         * specified type, or a subclass, in the chain of <code>Throwable</code>s.
              +949         * The method returns -1 if the specified type is not found in the chain.
              +950         * <p>
              +951         * NOTE: From v2.1, we have clarified the <code>Nestable</code> interface
              +952         * such that this method matches subclasses.
              +953         * If you want to NOT match subclasses, please use
              +954         * (which is avaiable in all versions of lang).
              +955         *
              +956         * @param type  the type to find, subclasses match, null returns -1
              +957         * @return index of the first occurrence of the type in the chain, or -1 if
              +958         * the type is not found
              +959         */
              +960        int indexOfThrowable(Class type);
              +961
              +962        /**
              +963         * Returns the index, numbered from 0, of the first <code>Throwable</code>
              +964         * that matches the specified type, or a subclass, in the chain of <code>Throwable</code>s
              +965         * with an index greater than or equal to the specified index.
              +966         * The method returns -1 if the specified type is not found in the chain.
              +967         * <p>
              +968         * NOTE: From v2.1, we have clarified the <code>Nestable</code> interface
              +969         * such that this method matches subclasses.
              +970         * If you want to NOT match subclasses, please use
              +971         * (which is avaiable in all versions of lang).
              +972         *
              +973         * @param type  the type to find, subclasses match, null returns -1
              +974         * @param fromIndex the index, numbered from 0, of the starting position in
              +975         * the chain to be searched
              +976         * @return index of the first occurrence of the type in the chain, or -1 if
              +977         * the type is not found
              +978         * @throws IndexOutOfBoundsException if the <code>fromIndex</code> argument
              +979         * is negative or not less than the count of <code>Throwable</code>s in the
              +980         * chain
              +981         */
              +982        int indexOfThrowable(Class type, int fromIndex);
              +983
              +984        /**
              +985         * Prints the stack trace of this exception to the specified print
              +986         * writer.  Includes information from the exception, if any,
              +987         * which caused this exception.
              +988         *
              +989         * @param out <code>PrintWriter</code> to use for output.
              +990         */
              +991        void printStackTrace(PrintWriter out);
              +992
              +993        /**
              +994         * Prints the stack trace of this exception to the specified print
              +995         * stream.  Includes information from the exception, if any,
              +996         * which caused this exception.
              +997         *
              +998         * @param out <code>PrintStream</code> to use for output.
              +999         */
              +1000        void printStackTrace(PrintStream out);
              +1001
              +1002        /**
              +1003         * Prints the stack trace for this exception only--root cause not
              +1004         * included--using the provided writer.  Used by
              +1005         * individual stack traces to a buffer.  The implementation of
              +1006         * this method should call
              +1007         * <code>super.printStackTrace(out);</code> in most cases.
              +1008         *
              +1009         * @param out The writer to use.
              +1010         */
              +1011        void printPartialStackTrace(PrintWriter out);
              +1012
              +1013    }
              +1014}
               
               
               
              @@ -1082,5 +1083,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.html b/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.html index 38092927..c6af83cc 100644 --- a/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.html +++ b/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsExceptionUtil.html @@ -1,1025 +1,1026 @@ - + Source code +
              -
              001/*
              -002 * Licensed to the Apache Software Foundation (ASF) under one or more
              -003 * contributor license agreements.  See the NOTICE file distributed with
              -004 * this work for additional information regarding copyright ownership.
              -005 * The ASF licenses this file to You under the Apache License, Version 2.0
              -006 * (the "License"); you may not use this file except in compliance with
              -007 * the License.  You may obtain a copy of the License at
              -008 *
              -009 *      http://www.apache.org/licenses/LICENSE-2.0
              -010 *
              -011 * Unless required by applicable law or agreed to in writing, software
              -012 * distributed under the License is distributed on an "AS IS" BASIS,
              -013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
              -014 * See the License for the specific language governing permissions and
              -015 * limitations under the License.
              -016 */
              -017package co.aikar.commands.apachecommonslang;
              -018
              -019import java.io.PrintStream;
              -020import java.io.PrintWriter;
              -021import java.io.StringWriter;
              -022import java.lang.reflect.Field;
              -023import java.lang.reflect.InvocationTargetException;
              -024import java.lang.reflect.Method;
              -025import java.sql.SQLException;
              -026import java.util.ArrayList;
              -027import java.util.Arrays;
              -028import java.util.List;
              -029import java.util.StringTokenizer;
              -030
              -031/**
              -032 * <p>Provides utilities for manipulating and examining
              -033 * <code>Throwable</code> objects.</p>
              -034 *
              -035 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
              -036 * @author Dmitri Plotnikov
              -037 * @author Stephen Colebourne
              -038 * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
              -039 * @author Pete Gieser
              -040 * @since 1.0
              -041 * @version $Id$
              -042 */
              -043public class ApacheCommonsExceptionUtil {
              -044    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
              -045
              -046    /**
              -047     * <p>Used when printing stack frames to denote the start of a
              -048     * wrapped exception.</p>
              -049     *
              -050     * <p>Package private for accessibility by test suite.</p>
              -051     */
              -052    static final String WRAPPED_MARKER = " [wrapped] ";
              -053
              -054    /**
              -055     * <p>The names of methods commonly used to access a wrapped exception.</p>
              -056     */
              -057    private static String[] CAUSE_METHOD_NAMES = {
              -058            "getCause",
              -059            "getNextException",
              -060            "getTargetException",
              -061            "getException",
              -062            "getSourceException",
              -063            "getRootCause",
              -064            "getCausedByException",
              -065            "getNested",
              -066            "getLinkedException",
              -067            "getNestedException",
              -068            "getLinkedCause",
              -069            "getThrowable",
              -070    };
              -071
              -072    /**
              -073     * <p>The Method object for Java 1.4 getCause.</p>
              -074     */
              -075    private static final Method THROWABLE_CAUSE_METHOD;
              -076
              -077    /**
              -078     * <p>The Method object for Java 1.4 initCause.</p>
              -079     */
              -080    private static final Method THROWABLE_INITCAUSE_METHOD;
              -081
              -082    static {
              -083        Method causeMethod;
              -084        try {
              -085            causeMethod = Throwable.class.getMethod("getCause", null);
              -086        } catch (Exception e) {
              -087            causeMethod = null;
              -088        }
              -089        THROWABLE_CAUSE_METHOD = causeMethod;
              -090        try {
              -091            causeMethod = Throwable.class.getMethod("initCause", Throwable.class);
              -092        } catch (Exception e) {
              -093            causeMethod = null;
              -094        }
              -095        THROWABLE_INITCAUSE_METHOD = causeMethod;
              -096    }
              -097
              -098    /**
              -099     * <p>
              -100     * Public constructor allows an instance of <code>ExceptionUtils</code> to be created, although that is not
              -101     * normally necessary.
              -102     * </p>
              -103     */
              -104    public ApacheCommonsExceptionUtil() {
              -105        super();
              -106    }
              -107
              -108    //-----------------------------------------------------------------------
              -109    /**
              -110     * <p>Adds to the list of method names used in the search for <code>Throwable</code>
              -111     * objects.</p>
              -112     *
              -113     * @param methodName  the methodName to add to the list, <code>null</code>
              -114     *  and empty strings are ignored
              -115     * @since 2.0
              -116     */
              -117    public static void addCauseMethodName(String methodName) {
              -118        if (methodName != null && !methodName.isEmpty() && !isCauseMethodName(methodName)) {
              -119            List list = getCauseMethodNameList();
              -120            if (list.add(methodName)) {
              -121                CAUSE_METHOD_NAMES = toArray(list);
              -122            }
              -123        }
              -124    }
              -125
              -126    /**
              -127     * <p>Removes from the list of method names used in the search for <code>Throwable</code>
              -128     * objects.</p>
              -129     *
              -130     * @param methodName  the methodName to remove from the list, <code>null</code>
              -131     *  and empty strings are ignored
              -132     * @since 2.1
              -133     */
              -134    public static void removeCauseMethodName(String methodName) {
              -135        if (methodName != null && !methodName.isEmpty()) {
              -136            List list = getCauseMethodNameList();
              -137            if (list.remove(methodName)) {
              -138                CAUSE_METHOD_NAMES = toArray(list);
              -139            }
              -140        }
              -141    }
              -142
              -143    /**
              -144     * <p>Sets the cause of a <code>Throwable</code> using introspection, allowing
              -145     * source code compatibility between pre-1.4 and post-1.4 Java releases.</p>
              -146     *
              -147     * <p>The typical use of this method is inside a constructor as in
              -148     * the following example:</p>
              -149     *
              -150     * <pre>
              -151     * import org.apache.commons.lang.exception.ExceptionUtils;
              -152     *
              -153     * public class MyException extends Exception {
              -154     *
              -155     *    public MyException(String msg) {
              -156     *       super(msg);
              -157     *    }
              -158     *
              -159     *    public MyException(String msg, Throwable cause) {
              -160     *       super(msg);
              -161     *       ExceptionUtils.setCause(this, cause);
              -162     *    }
              -163     * }
              -164     * </pre>
              -165     *
              -166     * @param target  the target <code>Throwable</code>
              -167     * @param cause  the <code>Throwable</code> to set in the target
              -168     * @return a <code>true</code> if the target has been modified
              -169     * @since 2.2
              -170     */
              -171    public static boolean setCause(Throwable target, Throwable cause) {
              -172        if (target == null) {
              -173            throw new IllegalArgumentException("target");
              -174        }
              -175        Object[] causeArgs = new Object[]{cause};
              -176        boolean modifiedTarget = false;
              -177        if (THROWABLE_INITCAUSE_METHOD != null) {
              -178            try {
              -179                THROWABLE_INITCAUSE_METHOD.invoke(target, causeArgs);
              -180                modifiedTarget = true;
              -181            } catch (IllegalAccessException ignored) {
              -182                // Exception ignored.
              -183            } catch (InvocationTargetException ignored) {
              -184                // Exception ignored.
              -185            }
              -186        }
              -187        try {
              -188            Method setCauseMethod = target.getClass().getMethod("setCause", Throwable.class);
              -189            setCauseMethod.invoke(target, causeArgs);
              -190            modifiedTarget = true;
              -191        } catch (NoSuchMethodException ignored) {
              -192            // Exception ignored.
              -193        } catch (IllegalAccessException ignored) {
              -194            // Exception ignored.
              -195        } catch (InvocationTargetException ignored) {
              -196            // Exception ignored.
              -197        }
              -198        return modifiedTarget;
              -199    }
              -200
              -201    /**
              -202     * Returns the given list as a <code>String[]</code>.
              -203     * @param list a list to transform.
              -204     * @return the given list as a <code>String[]</code>.
              -205     */
              -206    private static String[] toArray(List list) {
              -207        return (String[]) list.toArray(new String[list.size()]);
              -208    }
              -209
              -210    /**
              -211     * Returns {@link #CAUSE_METHOD_NAMES} as a List.
              -212     *
              -213     * @return {@link #CAUSE_METHOD_NAMES} as a List.
              -214     */
              -215    private static ArrayList getCauseMethodNameList() {
              -216        return new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));
              -217    }
              -218
              -219    /**
              -220     * <p>Tests if the list of method names used in the search for <code>Throwable</code>
              -221     * objects include the given name.</p>
              -222     *
              -223     * @param methodName  the methodName to search in the list.
              -224     * @return if the list of method names used in the search for <code>Throwable</code>
              -225     *  objects include the given name.
              -226     * @since 2.1
              -227     */
              -228    public static boolean isCauseMethodName(String methodName) {
              -229        return ApacheCommonsLangUtil.indexOf(CAUSE_METHOD_NAMES, methodName) >= 0;
              -230    }
              -231
              -232    //-----------------------------------------------------------------------
              -233    /**
              -234     * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
              -235     *
              -236     * <p>The method searches for methods with specific names that return a
              -237     * <code>Throwable</code> object. This will pick up most wrapping exceptions,
              -238     * including those from JDK 1.4, and
              -239     * The method names can be added to using {@link #addCauseMethodName(String)}.</p>
              -240     *
              -241     * <p>The default list searched for are:</p>
              -242     * <ul>
              -243     *  <li><code>getCause()</code></li>
              -244     *  <li><code>getNextException()</code></li>
              -245     *  <li><code>getTargetException()</code></li>
              -246     *  <li><code>getException()</code></li>
              -247     *  <li><code>getSourceException()</code></li>
              -248     *  <li><code>getRootCause()</code></li>
              -249     *  <li><code>getCausedByException()</code></li>
              -250     *  <li><code>getNested()</code></li>
              -251     * </ul>
              -252     *
              -253     * <p>In the absence of any such method, the object is inspected for a
              -254     * <code>detail</code> field assignable to a <code>Throwable</code>.</p>
              -255     *
              -256     * <p>If none of the above is found, returns <code>null</code>.</p>
              -257     *
              -258     * @param throwable  the throwable to introspect for a cause, may be null
              -259     * @return the cause of the <code>Throwable</code>,
              -260     *  <code>null</code> if none found or null throwable input
              -261     * @since 1.0
              -262     */
              -263    public static Throwable getCause(Throwable throwable) {
              -264        return getCause(throwable, CAUSE_METHOD_NAMES);
              -265    }
              -266
              -267    /**
              -268     * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
              -269     *
              -270     * <ol>
              -271     * <li>Try known exception types.</li>
              -272     * <li>Try the supplied array of method names.</li>
              -273     * <li>Try the field 'detail'.</li>
              -274     * </ol>
              -275     *
              -276     * <p>A <code>null</code> set of method names means use the default set.
              -277     * A <code>null</code> in the set of method names will be ignored.</p>
              -278     *
              -279     * @param throwable  the throwable to introspect for a cause, may be null
              -280     * @param methodNames  the method names, null treated as default set
              -281     * @return the cause of the <code>Throwable</code>,
              -282     *  <code>null</code> if none found or null throwable input
              -283     * @since 1.0
              -284     */
              -285    public static Throwable getCause(Throwable throwable, String[] methodNames) {
              -286        if (throwable == null) {
              -287            return null;
              -288        }
              -289        Throwable cause = getCauseUsingWellKnownTypes(throwable);
              -290        if (cause == null) {
              -291            if (methodNames == null) {
              -292                methodNames = CAUSE_METHOD_NAMES;
              -293            }
              -294            for (int i = 0; i < methodNames.length; i++) {
              -295                String methodName = methodNames[i];
              -296                if (methodName != null) {
              -297                    cause = getCauseUsingMethodName(throwable, methodName);
              -298                    if (cause != null) {
              -299                        break;
              -300                    }
              -301                }
              -302            }
              -303
              -304            if (cause == null) {
              -305                cause = getCauseUsingFieldName(throwable, "detail");
              -306            }
              -307        }
              -308        return cause;
              -309    }
              -310
              -311    /**
              -312     * <p>Introspects the <code>Throwable</code> to obtain the root cause.</p>
              -313     *
              -314     * <p>This method walks through the exception chain to the last element,
              -315     * "root" of the tree, using {@link #getCause(Throwable)}, and
              -316     * returns that exception.</p>
              -317     *
              -318     * <p>From version 2.2, this method handles recursive cause structures
              -319     * that might otherwise cause infinite loops. If the throwable parameter
              -320     * has a cause of itself, then null will be returned. If the throwable
              -321     * parameter cause chain loops, the last element in the chain before the
              -322     * loop is returned.</p>
              -323     *
              -324     * @param throwable  the throwable to get the root cause for, may be null
              -325     * @return the root cause of the <code>Throwable</code>,
              -326     *  <code>null</code> if none found or null throwable input
              -327     */
              -328    public static Throwable getRootCause(Throwable throwable) {
              -329        List list = getThrowableList(throwable);
              -330        return (list.size() < 2 ? null : (Throwable)list.get(list.size() - 1));
              -331    }
              -332
              -333    /**
              -334     * <p>Finds a <code>Throwable</code> for known types.</p>
              -335     *
              -336     * <p>Uses <code>instanceof</code> checks to examine the exception,
              -337     * looking for well known types which could contain chained or
              -338     * wrapped exceptions.</p>
              -339     *
              -340     * @param throwable  the exception to examine
              -341     * @return the wrapped exception, or <code>null</code> if not found
              -342     */
              -343    private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
              -344        if (throwable instanceof Nestable) {
              -345            return throwable.getCause();
              -346        } else if (throwable instanceof SQLException) {
              -347            return ((SQLException) throwable).getNextException();
              -348        } else if (throwable instanceof InvocationTargetException) {
              -349            return ((InvocationTargetException) throwable).getTargetException();
              -350        } else {
              -351            return null;
              -352        }
              -353    }
              -354
              -355    /**
              -356     * <p>Finds a <code>Throwable</code> by method name.</p>
              -357     *
              -358     * @param throwable  the exception to examine
              -359     * @param methodName  the name of the method to find and invoke
              -360     * @return the wrapped exception, or <code>null</code> if not found
              -361     */
              -362    private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName) {
              -363        Method method = null;
              -364        try {
              -365            method = throwable.getClass().getMethod(methodName, null);
              -366        } catch (NoSuchMethodException ignored) {
              -367            // exception ignored
              -368        } catch (SecurityException ignored) {
              -369            // exception ignored
              -370        }
              -371
              -372        if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
              -373            try {
              -374                return (Throwable) method.invoke(throwable);
              -375            } catch (IllegalAccessException ignored) {
              -376                // exception ignored
              -377            } catch (IllegalArgumentException ignored) {
              -378                // exception ignored
              -379            } catch (InvocationTargetException ignored) {
              -380                // exception ignored
              -381            }
              -382        }
              -383        return null;
              -384    }
              -385
              -386    /**
              -387     * <p>Finds a <code>Throwable</code> by field name.</p>
              -388     *
              -389     * @param throwable  the exception to examine
              -390     * @param fieldName  the name of the attribute to examine
              -391     * @return the wrapped exception, or <code>null</code> if not found
              -392     */
              -393    private static Throwable getCauseUsingFieldName(Throwable throwable, String fieldName) {
              -394        Field field = null;
              -395        try {
              -396            field = throwable.getClass().getField(fieldName);
              -397        } catch (NoSuchFieldException ignored) {
              -398            // exception ignored
              -399        } catch (SecurityException ignored) {
              -400            // exception ignored
              -401        }
              -402
              -403        if (field != null && Throwable.class.isAssignableFrom(field.getType())) {
              -404            try {
              -405                return (Throwable) field.get(throwable);
              -406            } catch (IllegalAccessException ignored) {
              -407                // exception ignored
              -408            } catch (IllegalArgumentException ignored) {
              -409                // exception ignored
              -410            }
              -411        }
              -412        return null;
              -413    }
              -414
              -415    //-----------------------------------------------------------------------
              -416    /**
              -417     * <p>Checks if the Throwable class has a <code>getCause</code> method.</p>
              -418     *
              -419     * <p>This is true for JDK 1.4 and above.</p>
              -420     *
              -421     * @return true if Throwable is nestable
              -422     * @since 2.0
              -423     */
              -424    public static boolean isThrowableNested() {
              -425        return THROWABLE_CAUSE_METHOD != null;
              -426    }
              -427
              -428    /**
              -429     * <p>Checks whether this <code>Throwable</code> class can store a cause.</p>
              -430     *
              -431     * <p>This method does <b>not</b> check whether it actually does store a cause.<p>
              -432     *
              -433     * @param throwable  the <code>Throwable</code> to examine, may be null
              -434     * @return boolean <code>true</code> if nested otherwise <code>false</code>
              -435     * @since 2.0
              -436     */
              -437    public static boolean isNestedThrowable(Throwable throwable) {
              -438        if (throwable == null) {
              -439            return false;
              -440        }
              -441
              -442        if (throwable instanceof Nestable) {
              -443            return true;
              -444        } else if (throwable instanceof SQLException) {
              -445            return true;
              -446        } else if (throwable instanceof InvocationTargetException) {
              -447            return true;
              -448        } else if (isThrowableNested()) {
              -449            return true;
              -450        }
              -451
              -452        Class cls = throwable.getClass();
              -453        for (int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++) {
              -454            try {
              -455                Method method = cls.getMethod(CAUSE_METHOD_NAMES[i], null);
              -456                if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
              -457                    return true;
              -458                }
              -459            } catch (NoSuchMethodException ignored) {
              -460                // exception ignored
              -461            } catch (SecurityException ignored) {
              -462                // exception ignored
              -463            }
              -464        }
              -465
              -466        try {
              -467            Field field = cls.getField("detail");
              -468            if (field != null) {
              -469                return true;
              -470            }
              -471        } catch (NoSuchFieldException ignored) {
              -472            // exception ignored
              -473        } catch (SecurityException ignored) {
              -474            // exception ignored
              -475        }
              -476
              -477        return false;
              -478    }
              -479
              -480    //-----------------------------------------------------------------------
              -481    /**
              -482     * <p>Counts the number of <code>Throwable</code> objects in the
              -483     * exception chain.</p>
              -484     *
              -485     * <p>A throwable without cause will return <code>1</code>.
              -486     * A throwable with one cause will return <code>2</code> and so on.
              -487     * A <code>null</code> throwable will return <code>0</code>.</p>
              -488     *
              -489     * <p>From version 2.2, this method handles recursive cause structures
              -490     * that might otherwise cause infinite loops. The cause chain is
              -491     * processed until the end is reached, or until the next item in the
              -492     * chain is already in the result set.</p>
              -493     *
              -494     * @param throwable  the throwable to inspect, may be null
              -495     * @return the count of throwables, zero if null input
              -496     */
              -497    public static int getThrowableCount(Throwable throwable) {
              -498        return getThrowableList(throwable).size();
              -499    }
              -500
              -501    /**
              -502     * <p>Returns the list of <code>Throwable</code> objects in the
              -503     * exception chain.</p>
              -504     *
              -505     * <p>A throwable without cause will return an array containing
              -506     * one element - the input throwable.
              -507     * A throwable with one cause will return an array containing
              -508     * two elements. - the input throwable and the cause throwable.
              -509     * A <code>null</code> throwable will return an array of size zero.</p>
              -510     *
              -511     * <p>From version 2.2, this method handles recursive cause structures
              -512     * that might otherwise cause infinite loops. The cause chain is
              -513     * processed until the end is reached, or until the next item in the
              -514     * chain is already in the result set.</p>
              -515     *
              -516     * @see #getThrowableList(Throwable)
              -517     * @param throwable  the throwable to inspect, may be null
              -518     * @return the array of throwables, never null
              -519     */
              -520    public static Throwable[] getThrowables(Throwable throwable) {
              -521        List list = getThrowableList(throwable);
              -522        return (Throwable[]) list.toArray(new Throwable[list.size()]);
              -523    }
              -524
              -525    /**
              -526     * <p>Returns the list of <code>Throwable</code> objects in the
              -527     * exception chain.</p>
              -528     *
              -529     * <p>A throwable without cause will return a list containing
              -530     * one element - the input throwable.
              -531     * A throwable with one cause will return a list containing
              -532     * two elements. - the input throwable and the cause throwable.
              -533     * A <code>null</code> throwable will return a list of size zero.</p>
              -534     *
              -535     * <p>This method handles recursive cause structures that might
              -536     * otherwise cause infinite loops. The cause chain is processed until
              -537     * the end is reached, or until the next item in the chain is already
              -538     * in the result set.</p>
              -539     *
              -540     * @param throwable  the throwable to inspect, may be null
              -541     * @return the list of throwables, never null
              -542     * @since Commons Lang 2.2
              -543     */
              -544    public static List getThrowableList(Throwable throwable) {
              -545        List list = new ArrayList();
              -546        while (throwable != null && list.contains(throwable) == false) {
              -547            list.add(throwable);
              -548            throwable = getCause(throwable);
              -549        }
              -550        return list;
              -551    }
              -552
              -553    //-----------------------------------------------------------------------
              -554    /**
              -555     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              -556     * that matches the specified class (exactly) in the exception chain.
              -557     * Subclasses of the specified class do not match - see
              -558     * {@link #indexOfType(Throwable, Class)} for the opposite.</p>
              -559     *
              -560     * <p>A <code>null</code> throwable returns <code>-1</code>.
              -561     * A <code>null</code> type returns <code>-1</code>.
              -562     * No match in the chain returns <code>-1</code>.</p>
              -563     *
              -564     * @param throwable  the throwable to inspect, may be null
              -565     * @param clazz  the class to search for, subclasses do not match, null returns -1
              -566     * @return the index into the throwable chain, -1 if no match or null input
              -567     */
              -568    public static int indexOfThrowable(Throwable throwable, Class clazz) {
              -569        return indexOf(throwable, clazz, 0, false);
              -570    }
              -571
              -572    /**
              -573     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              -574     * that matches the specified type in the exception chain from
              -575     * a specified index.
              -576     * Subclasses of the specified class do not match - see
              -577     * {@link #indexOfType(Throwable, Class, int)} for the opposite.</p>
              -578     *
              -579     * <p>A <code>null</code> throwable returns <code>-1</code>.
              -580     * A <code>null</code> type returns <code>-1</code>.
              -581     * No match in the chain returns <code>-1</code>.
              -582     * A negative start index is treated as zero.
              -583     * A start index greater than the number of throwables returns <code>-1</code>.</p>
              -584     *
              -585     * @param throwable  the throwable to inspect, may be null
              -586     * @param clazz  the class to search for, subclasses do not match, null returns -1
              -587     * @param fromIndex  the (zero based) index of the starting position,
              -588     *  negative treated as zero, larger than chain size returns -1
              -589     * @return the index into the throwable chain, -1 if no match or null input
              -590     */
              -591    public static int indexOfThrowable(Throwable throwable, Class clazz, int fromIndex) {
              -592        return indexOf(throwable, clazz, fromIndex, false);
              -593    }
              -594
              -595    //-----------------------------------------------------------------------
              -596    /**
              -597     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              -598     * that matches the specified class or subclass in the exception chain.
              -599     * Subclasses of the specified class do match - see
              -600     * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
              -601     *
              -602     * <p>A <code>null</code> throwable returns <code>-1</code>.
              -603     * A <code>null</code> type returns <code>-1</code>.
              -604     * No match in the chain returns <code>-1</code>.</p>
              -605     *
              -606     * @param throwable  the throwable to inspect, may be null
              -607     * @param type  the type to search for, subclasses match, null returns -1
              -608     * @return the index into the throwable chain, -1 if no match or null input
              -609     * @since 2.1
              -610     */
              -611    public static int indexOfType(Throwable throwable, Class type) {
              -612        return indexOf(throwable, type, 0, true);
              -613    }
              -614
              -615    /**
              -616     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              -617     * that matches the specified type in the exception chain from
              -618     * a specified index.
              -619     * Subclasses of the specified class do match - see
              -620     * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
              -621     *
              -622     * <p>A <code>null</code> throwable returns <code>-1</code>.
              -623     * A <code>null</code> type returns <code>-1</code>.
              -624     * No match in the chain returns <code>-1</code>.
              -625     * A negative start index is treated as zero.
              -626     * A start index greater than the number of throwables returns <code>-1</code>.</p>
              -627     *
              -628     * @param throwable  the throwable to inspect, may be null
              -629     * @param type  the type to search for, subclasses match, null returns -1
              -630     * @param fromIndex  the (zero based) index of the starting position,
              -631     *  negative treated as zero, larger than chain size returns -1
              -632     * @return the index into the throwable chain, -1 if no match or null input
              -633     * @since 2.1
              -634     */
              -635    public static int indexOfType(Throwable throwable, Class type, int fromIndex) {
              -636        return indexOf(throwable, type, fromIndex, true);
              -637    }
              -638
              -639    /**
              -640     * <p>Worker method for the <code>indexOfType</code> methods.</p>
              -641     *
              -642     * @param throwable  the throwable to inspect, may be null
              -643     * @param type  the type to search for, subclasses match, null returns -1
              -644     * @param fromIndex  the (zero based) index of the starting position,
              -645     *  negative treated as zero, larger than chain size returns -1
              -646     * @param subclass if <code>true</code>, compares with {@link Class#isAssignableFrom(Class)}, otherwise compares
              -647     * using references
              -648     * @return index of the <code>type</code> within throwables nested withing the specified <code>throwable</code>
              -649     */
              -650    private static int indexOf(Throwable throwable, Class type, int fromIndex, boolean subclass) {
              -651        if (throwable == null || type == null) {
              -652            return -1;
              -653        }
              -654        if (fromIndex < 0) {
              -655            fromIndex = 0;
              -656        }
              -657        Throwable[] throwables = getThrowables(throwable);
              -658        if (fromIndex >= throwables.length) {
              -659            return -1;
              -660        }
              -661        if (subclass) {
              -662            for (int i = fromIndex; i < throwables.length; i++) {
              -663                if (type.isAssignableFrom(throwables[i].getClass())) {
              -664                    return i;
              -665                }
              -666            }
              -667        } else {
              -668            for (int i = fromIndex; i < throwables.length; i++) {
              -669                if (type.equals(throwables[i].getClass())) {
              -670                    return i;
              -671                }
              -672            }
              -673        }
              -674        return -1;
              -675    }
              -676
              -677    /**
              -678     * <p>Removes common frames from the cause trace given the two stack traces.</p>
              -679     *
              -680     * @param causeFrames  stack trace of a cause throwable
              -681     * @param wrapperFrames  stack trace of a wrapper throwable
              -682     * @throws IllegalArgumentException if either argument is null
              -683     * @since 2.0
              -684     */
              -685    public static void removeCommonFrames(List causeFrames, List wrapperFrames) {
              -686        if (causeFrames == null || wrapperFrames == null) {
              -687            throw new IllegalArgumentException("The List must not be null");
              -688        }
              -689        int causeFrameIndex = causeFrames.size() - 1;
              -690        int wrapperFrameIndex = wrapperFrames.size() - 1;
              -691        while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
              -692            // Remove the frame from the cause trace if it is the same
              -693            // as in the wrapper trace
              -694            String causeFrame = (String) causeFrames.get(causeFrameIndex);
              -695            String wrapperFrame = (String) wrapperFrames.get(wrapperFrameIndex);
              -696            if (causeFrame.equals(wrapperFrame)) {
              -697                causeFrames.remove(causeFrameIndex);
              -698            }
              -699            causeFrameIndex--;
              -700            wrapperFrameIndex--;
              -701        }
              -702    }
              -703
              -704    //-----------------------------------------------------------------------
              -705    /**
              -706     * <p>A way to get the entire nested stack-trace of an throwable.</p>
              -707     *
              -708     * <p>The result of this method is highly dependent on the JDK version
              -709     * and whether the exceptions override printStackTrace or not.</p>
              -710     *
              -711     * @param throwable  the <code>Throwable</code> to be examined
              -712     * @return the nested stack trace, with the root cause first
              -713     * @since 2.0
              -714     */
              -715    public static String getFullStackTrace(Throwable throwable) {
              -716        StringWriter sw = new StringWriter();
              -717        PrintWriter pw = new PrintWriter(sw, true);
              -718        Throwable[] ts = getThrowables(throwable);
              -719        for (int i = 0; i < ts.length; i++) {
              -720            ts[i].printStackTrace(pw);
              -721            if (isNestedThrowable(ts[i])) {
              -722                break;
              -723            }
              -724        }
              -725        return sw.getBuffer().toString();
              -726    }
              -727
              -728    //-----------------------------------------------------------------------
              -729    /**
              -730     * <p>Gets the stack trace from a Throwable as a String.</p>
              -731     *
              -732     * <p>The result of this method vary by JDK version as this method
              -733     * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
              -734     * On JDK1.3 and earlier, the cause exception will not be shown
              -735     * unless the specified throwable alters printStackTrace.</p>
              -736     *
              -737     * @param throwable  the <code>Throwable</code> to be examined
              -738     * @return the stack trace as generated by the exception's
              -739     *  <code>printStackTrace(PrintWriter)</code> method
              -740     */
              -741    public static String getStackTrace(Throwable throwable) {
              -742        StringWriter sw = new StringWriter();
              -743        PrintWriter pw = new PrintWriter(sw, true);
              -744        throwable.printStackTrace(pw);
              -745        return sw.getBuffer().toString();
              -746    }
              -747
              -748    /**
              -749     * <p>Captures the stack trace associated with the specified
              -750     * <code>Throwable</code> object, decomposing it into a list of
              -751     * stack frames.</p>
              -752     *
              -753     * <p>The result of this method vary by JDK version as this method
              -754     * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
              -755     * On JDK1.3 and earlier, the cause exception will not be shown
              -756     * unless the specified throwable alters printStackTrace.</p>
              -757     *
              -758     * @param throwable  the <code>Throwable</code> to examine, may be null
              -759     * @return an array of strings describing each stack frame, never null
              -760     */
              -761//    public static String[] getStackFrames(Throwable throwable) {
              -762//        if (throwable == null) {
              -763//            return ArrayUtils.EMPTY_STRING_ARRAY;
              -764//        }
              -765//        return getStackFrames(getStackTrace(throwable));
              -766//    }
              -767
              -768    //-----------------------------------------------------------------------
              -769    /**
              -770     * <p>Returns an array where each element is a line from the argument.</p>
              -771     *
              -772     * <p>The end of line is determined by the value of {@link SystemUtils#LINE_SEPARATOR}.</p>
              -773     *
              -774     * <p>Functionality shared between the
              -775     * <code>getStackFrames(Throwable)</code> methods of this and the
              -776     * {@link org.apache.commons.lang.exception.NestableDelegate} classes.</p>
              -777     *
              -778     * @param stackTrace  a stack trace String
              -779     * @return an array where each element is a line from the argument
              -780     */
              -781//    static String[] getStackFrames(String stackTrace) {
              -782//        String linebreak = SystemUtils.LINE_SEPARATOR;
              -783//        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
              -784//        List list = new ArrayList();
              -785//        while (frames.hasMoreTokens()) {
              -786//            list.add(frames.nextToken());
              -787//        }
              -788//        return toArray(list);
              -789//    }
              -790
              -791    /**
              -792     * <p>Produces a <code>List</code> of stack frames - the message
              -793     * is not included. Only the trace of the specified exception is
              -794     * returned, any caused by trace is stripped.</p>
              -795     *
              -796     * <p>This works in most cases - it will only fail if the exception
              -797     * message contains a line that starts with:
              -798     * <code>&quot;&nbsp;&nbsp;&nbsp;at&quot;.</code></p>
              -799     *
              -800     * @param t is any throwable
              -801     * @return List of stack frames
              -802     */
              -803    static List getStackFrameList(Throwable t) {
              -804        String stackTrace = getStackTrace(t);
              -805        String linebreak = LINE_SEPARATOR;
              -806        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
              -807        List list = new ArrayList();
              -808        boolean traceStarted = false;
              -809        while (frames.hasMoreTokens()) {
              -810            String token = frames.nextToken();
              -811            // Determine if the line starts with <whitespace>at
              -812            int at = token.indexOf("at");
              -813            if (at != -1 && token.substring(0, at).trim().length() == 0) {
              -814                traceStarted = true;
              -815                list.add(token);
              -816            } else if (traceStarted) {
              -817                break;
              -818            }
              -819        }
              -820        return list;
              -821    }
              -822
              -823    //-----------------------------------------------------------------------
              -824    /**
              -825     * Gets a short message summarising the exception.
              -826     * <p>
              -827     * The message returned is of the form
              -828     * {ClassNameWithoutPackage}: {ThrowableMessage}
              -829     *
              -830     * @param th  the throwable to get a message for, null returns empty string
              -831     * @return the message, non-null
              -832     * @since Commons Lang 2.2
              -833     */
              -834//    public static String getMessage(Throwable th) {
              -835//        if (th == null) {
              -836//            return "";
              -837//        }
              -838//        String clsName = ClassUtils.getShortClassName(th, null);
              -839//        String msg = th.getMessage();
              -840//        return clsName + ": " + StringUtils.defaultString(msg);
              -841//    }
              -842
              -843    //-----------------------------------------------------------------------
              -844    /**
              -845     * Gets a short message summarising the root cause exception.
              -846     * <p>
              -847     * The message returned is of the form
              -848     * {ClassNameWithoutPackage}: {ThrowableMessage}
              -849     *
              -850     * @param th  the throwable to get a message for, null returns empty string
              -851     * @return the message, non-null
              -852     * @since Commons Lang 2.2
              -853     */
              -854//    public static String getRootCauseMessage(Throwable th) {
              -855//        Throwable root = ExceptionUtils.getRootCause(th);
              -856//        root = (root == null ? th : root);
              -857//        return getMessage(root);
              -858//    }
              -859
              -860    /**
              -861     * An interface to be implemented by {@link java.lang.Throwable}
              -862     * extensions which would like to be able to nest root exceptions
              -863     * inside themselves.
              -864     *
              -865     * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
              -866     * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
              -867     * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
              -868     * @author Pete Gieser
              -869     * @since 1.0
              -870     * @version $Id$
              -871     */
              -872    public interface Nestable {
              -873
              -874        /**
              -875         * Returns the reference to the exception or error that caused the
              -876         * exception implementing the <code>Nestable</code> to be thrown.
              -877         *
              -878         * @return throwable that caused the original exception
              -879         */
              -880        Throwable getCause();
              -881
              -882        /**
              -883         * Returns the error message of this and any nested
              -884         * <code>Throwable</code>.
              -885         *
              -886         * @return the error message
              -887         */
              -888        String getMessage();
              -889
              -890        /**
              -891         * Returns the error message of the <code>Throwable</code> in the chain
              -892         * of <code>Throwable</code>s at the specified index, numbered from 0.
              -893         *
              -894         * @param index the index of the <code>Throwable</code> in the chain of
              -895         * <code>Throwable</code>s
              -896         * @return the error message, or null if the <code>Throwable</code> at the
              -897         * specified index in the chain does not contain a message
              -898         * @throws IndexOutOfBoundsException if the <code>index</code> argument is
              -899         * negative or not less than the count of <code>Throwable</code>s in the
              -900         * chain
              -901         */
              -902        String getMessage(int index);
              -903
              -904        /**
              -905         * Returns the error message of this and any nested <code>Throwable</code>s
              -906         * in an array of Strings, one element for each message. Any
              -907         * <code>Throwable</code> not containing a message is represented in the
              -908         * array by a null. This has the effect of cause the length of the returned
              -909         * array to be equal to the result of the {@link #getThrowableCount()}
              -910         * operation.
              -911         *
              -912         * @return the error messages
              -913         */
              -914        String[] getMessages();
              -915
              -916        /**
              -917         * Returns the <code>Throwable</code> in the chain of
              -918         * <code>Throwable</code>s at the specified index, numbered from 0.
              -919         *
              -920         * @param index the index, numbered from 0, of the <code>Throwable</code> in
              -921         * the chain of <code>Throwable</code>s
              -922         * @return the <code>Throwable</code>
              -923         * @throws IndexOutOfBoundsException if the <code>index</code> argument is
              -924         * negative or not less than the count of <code>Throwable</code>s in the
              -925         * chain
              -926         */
              -927        Throwable getThrowable(int index);
              -928
              -929        /**
              -930         * Returns the number of nested <code>Throwable</code>s represented by
              -931         * this <code>Nestable</code>, including this <code>Nestable</code>.
              -932         *
              -933         * @return the throwable count
              -934         */
              -935        int getThrowableCount();
              -936
              -937        /**
              -938         * Returns this <code>Nestable</code> and any nested <code>Throwable</code>s
              -939         * in an array of <code>Throwable</code>s, one element for each
              -940         * <code>Throwable</code>.
              -941         *
              -942         * @return the <code>Throwable</code>s
              -943         */
              -944        Throwable[] getThrowables();
              -945
              -946        /**
              -947         * Returns the index, numbered from 0, of the first occurrence of the
              -948         * specified type, or a subclass, in the chain of <code>Throwable</code>s.
              -949         * The method returns -1 if the specified type is not found in the chain.
              -950         * <p>
              -951         * NOTE: From v2.1, we have clarified the <code>Nestable</code> interface
              -952         * such that this method matches subclasses.
              -953         * If you want to NOT match subclasses, please use
              -954         * (which is avaiable in all versions of lang).
              -955         *
              -956         * @param type  the type to find, subclasses match, null returns -1
              -957         * @return index of the first occurrence of the type in the chain, or -1 if
              -958         * the type is not found
              -959         */
              -960        int indexOfThrowable(Class type);
              -961
              -962        /**
              -963         * Returns the index, numbered from 0, of the first <code>Throwable</code>
              -964         * that matches the specified type, or a subclass, in the chain of <code>Throwable</code>s
              -965         * with an index greater than or equal to the specified index.
              -966         * The method returns -1 if the specified type is not found in the chain.
              -967         * <p>
              -968         * NOTE: From v2.1, we have clarified the <code>Nestable</code> interface
              -969         * such that this method matches subclasses.
              -970         * If you want to NOT match subclasses, please use
              -971         * (which is avaiable in all versions of lang).
              -972         *
              -973         * @param type  the type to find, subclasses match, null returns -1
              -974         * @param fromIndex the index, numbered from 0, of the starting position in
              -975         * the chain to be searched
              -976         * @return index of the first occurrence of the type in the chain, or -1 if
              -977         * the type is not found
              -978         * @throws IndexOutOfBoundsException if the <code>fromIndex</code> argument
              -979         * is negative or not less than the count of <code>Throwable</code>s in the
              -980         * chain
              -981         */
              -982        int indexOfThrowable(Class type, int fromIndex);
              -983
              -984        /**
              -985         * Prints the stack trace of this exception to the specified print
              -986         * writer.  Includes information from the exception, if any,
              -987         * which caused this exception.
              -988         *
              -989         * @param out <code>PrintWriter</code> to use for output.
              -990         */
              -991        void printStackTrace(PrintWriter out);
              -992
              -993        /**
              -994         * Prints the stack trace of this exception to the specified print
              -995         * stream.  Includes information from the exception, if any,
              -996         * which caused this exception.
              -997         *
              -998         * @param out <code>PrintStream</code> to use for output.
              -999         */
              -1000        void printStackTrace(PrintStream out);
              -1001
              -1002        /**
              -1003         * Prints the stack trace for this exception only--root cause not
              -1004         * included--using the provided writer.  Used by
              -1005         * individual stack traces to a buffer.  The implementation of
              -1006         * this method should call
              -1007         * <code>super.printStackTrace(out);</code> in most cases.
              -1008         *
              -1009         * @param out The writer to use.
              -1010         */
              -1011        void printPartialStackTrace(PrintWriter out);
              -1012
              -1013    }
              -1014}
              +
              001/*
              +002 * Licensed to the Apache Software Foundation (ASF) under one or more
              +003 * contributor license agreements.  See the NOTICE file distributed with
              +004 * this work for additional information regarding copyright ownership.
              +005 * The ASF licenses this file to You under the Apache License, Version 2.0
              +006 * (the "License"); you may not use this file except in compliance with
              +007 * the License.  You may obtain a copy of the License at
              +008 *
              +009 *      http://www.apache.org/licenses/LICENSE-2.0
              +010 *
              +011 * Unless required by applicable law or agreed to in writing, software
              +012 * distributed under the License is distributed on an "AS IS" BASIS,
              +013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
              +014 * See the License for the specific language governing permissions and
              +015 * limitations under the License.
              +016 */
              +017package co.aikar.commands.apachecommonslang;
              +018
              +019import java.io.PrintStream;
              +020import java.io.PrintWriter;
              +021import java.io.StringWriter;
              +022import java.lang.reflect.Field;
              +023import java.lang.reflect.InvocationTargetException;
              +024import java.lang.reflect.Method;
              +025import java.sql.SQLException;
              +026import java.util.ArrayList;
              +027import java.util.Arrays;
              +028import java.util.List;
              +029import java.util.StringTokenizer;
              +030
              +031/**
              +032 * <p>Provides utilities for manipulating and examining
              +033 * <code>Throwable</code> objects.</p>
              +034 *
              +035 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
              +036 * @author Dmitri Plotnikov
              +037 * @author Stephen Colebourne
              +038 * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
              +039 * @author Pete Gieser
              +040 * @since 1.0
              +041 * @version $Id$
              +042 */
              +043public class ApacheCommonsExceptionUtil {
              +044    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
              +045
              +046    /**
              +047     * <p>Used when printing stack frames to denote the start of a
              +048     * wrapped exception.</p>
              +049     *
              +050     * <p>Package private for accessibility by test suite.</p>
              +051     */
              +052    static final String WRAPPED_MARKER = " [wrapped] ";
              +053
              +054    /**
              +055     * <p>The names of methods commonly used to access a wrapped exception.</p>
              +056     */
              +057    private static String[] CAUSE_METHOD_NAMES = {
              +058            "getCause",
              +059            "getNextException",
              +060            "getTargetException",
              +061            "getException",
              +062            "getSourceException",
              +063            "getRootCause",
              +064            "getCausedByException",
              +065            "getNested",
              +066            "getLinkedException",
              +067            "getNestedException",
              +068            "getLinkedCause",
              +069            "getThrowable",
              +070    };
              +071
              +072    /**
              +073     * <p>The Method object for Java 1.4 getCause.</p>
              +074     */
              +075    private static final Method THROWABLE_CAUSE_METHOD;
              +076
              +077    /**
              +078     * <p>The Method object for Java 1.4 initCause.</p>
              +079     */
              +080    private static final Method THROWABLE_INITCAUSE_METHOD;
              +081
              +082    static {
              +083        Method causeMethod;
              +084        try {
              +085            causeMethod = Throwable.class.getMethod("getCause", null);
              +086        } catch (Exception e) {
              +087            causeMethod = null;
              +088        }
              +089        THROWABLE_CAUSE_METHOD = causeMethod;
              +090        try {
              +091            causeMethod = Throwable.class.getMethod("initCause", Throwable.class);
              +092        } catch (Exception e) {
              +093            causeMethod = null;
              +094        }
              +095        THROWABLE_INITCAUSE_METHOD = causeMethod;
              +096    }
              +097
              +098    /**
              +099     * <p>
              +100     * Public constructor allows an instance of <code>ExceptionUtils</code> to be created, although that is not
              +101     * normally necessary.
              +102     * </p>
              +103     */
              +104    public ApacheCommonsExceptionUtil() {
              +105        super();
              +106    }
              +107
              +108    //-----------------------------------------------------------------------
              +109    /**
              +110     * <p>Adds to the list of method names used in the search for <code>Throwable</code>
              +111     * objects.</p>
              +112     *
              +113     * @param methodName  the methodName to add to the list, <code>null</code>
              +114     *  and empty strings are ignored
              +115     * @since 2.0
              +116     */
              +117    public static void addCauseMethodName(String methodName) {
              +118        if (methodName != null && !methodName.isEmpty() && !isCauseMethodName(methodName)) {
              +119            List list = getCauseMethodNameList();
              +120            if (list.add(methodName)) {
              +121                CAUSE_METHOD_NAMES = toArray(list);
              +122            }
              +123        }
              +124    }
              +125
              +126    /**
              +127     * <p>Removes from the list of method names used in the search for <code>Throwable</code>
              +128     * objects.</p>
              +129     *
              +130     * @param methodName  the methodName to remove from the list, <code>null</code>
              +131     *  and empty strings are ignored
              +132     * @since 2.1
              +133     */
              +134    public static void removeCauseMethodName(String methodName) {
              +135        if (methodName != null && !methodName.isEmpty()) {
              +136            List list = getCauseMethodNameList();
              +137            if (list.remove(methodName)) {
              +138                CAUSE_METHOD_NAMES = toArray(list);
              +139            }
              +140        }
              +141    }
              +142
              +143    /**
              +144     * <p>Sets the cause of a <code>Throwable</code> using introspection, allowing
              +145     * source code compatibility between pre-1.4 and post-1.4 Java releases.</p>
              +146     *
              +147     * <p>The typical use of this method is inside a constructor as in
              +148     * the following example:</p>
              +149     *
              +150     * <pre>
              +151     * import org.apache.commons.lang.exception.ExceptionUtils;
              +152     *
              +153     * public class MyException extends Exception {
              +154     *
              +155     *    public MyException(String msg) {
              +156     *       super(msg);
              +157     *    }
              +158     *
              +159     *    public MyException(String msg, Throwable cause) {
              +160     *       super(msg);
              +161     *       ExceptionUtils.setCause(this, cause);
              +162     *    }
              +163     * }
              +164     * </pre>
              +165     *
              +166     * @param target  the target <code>Throwable</code>
              +167     * @param cause  the <code>Throwable</code> to set in the target
              +168     * @return a <code>true</code> if the target has been modified
              +169     * @since 2.2
              +170     */
              +171    public static boolean setCause(Throwable target, Throwable cause) {
              +172        if (target == null) {
              +173            throw new IllegalArgumentException("target");
              +174        }
              +175        Object[] causeArgs = new Object[]{cause};
              +176        boolean modifiedTarget = false;
              +177        if (THROWABLE_INITCAUSE_METHOD != null) {
              +178            try {
              +179                THROWABLE_INITCAUSE_METHOD.invoke(target, causeArgs);
              +180                modifiedTarget = true;
              +181            } catch (IllegalAccessException ignored) {
              +182                // Exception ignored.
              +183            } catch (InvocationTargetException ignored) {
              +184                // Exception ignored.
              +185            }
              +186        }
              +187        try {
              +188            Method setCauseMethod = target.getClass().getMethod("setCause", Throwable.class);
              +189            setCauseMethod.invoke(target, causeArgs);
              +190            modifiedTarget = true;
              +191        } catch (NoSuchMethodException ignored) {
              +192            // Exception ignored.
              +193        } catch (IllegalAccessException ignored) {
              +194            // Exception ignored.
              +195        } catch (InvocationTargetException ignored) {
              +196            // Exception ignored.
              +197        }
              +198        return modifiedTarget;
              +199    }
              +200
              +201    /**
              +202     * Returns the given list as a <code>String[]</code>.
              +203     * @param list a list to transform.
              +204     * @return the given list as a <code>String[]</code>.
              +205     */
              +206    private static String[] toArray(List list) {
              +207        return (String[]) list.toArray(new String[list.size()]);
              +208    }
              +209
              +210    /**
              +211     * Returns {@link #CAUSE_METHOD_NAMES} as a List.
              +212     *
              +213     * @return {@link #CAUSE_METHOD_NAMES} as a List.
              +214     */
              +215    private static ArrayList getCauseMethodNameList() {
              +216        return new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));
              +217    }
              +218
              +219    /**
              +220     * <p>Tests if the list of method names used in the search for <code>Throwable</code>
              +221     * objects include the given name.</p>
              +222     *
              +223     * @param methodName  the methodName to search in the list.
              +224     * @return if the list of method names used in the search for <code>Throwable</code>
              +225     *  objects include the given name.
              +226     * @since 2.1
              +227     */
              +228    public static boolean isCauseMethodName(String methodName) {
              +229        return ApacheCommonsLangUtil.indexOf(CAUSE_METHOD_NAMES, methodName) >= 0;
              +230    }
              +231
              +232    //-----------------------------------------------------------------------
              +233    /**
              +234     * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
              +235     *
              +236     * <p>The method searches for methods with specific names that return a
              +237     * <code>Throwable</code> object. This will pick up most wrapping exceptions,
              +238     * including those from JDK 1.4, and
              +239     * The method names can be added to using {@link #addCauseMethodName(String)}.</p>
              +240     *
              +241     * <p>The default list searched for are:</p>
              +242     * <ul>
              +243     *  <li><code>getCause()</code></li>
              +244     *  <li><code>getNextException()</code></li>
              +245     *  <li><code>getTargetException()</code></li>
              +246     *  <li><code>getException()</code></li>
              +247     *  <li><code>getSourceException()</code></li>
              +248     *  <li><code>getRootCause()</code></li>
              +249     *  <li><code>getCausedByException()</code></li>
              +250     *  <li><code>getNested()</code></li>
              +251     * </ul>
              +252     *
              +253     * <p>In the absence of any such method, the object is inspected for a
              +254     * <code>detail</code> field assignable to a <code>Throwable</code>.</p>
              +255     *
              +256     * <p>If none of the above is found, returns <code>null</code>.</p>
              +257     *
              +258     * @param throwable  the throwable to introspect for a cause, may be null
              +259     * @return the cause of the <code>Throwable</code>,
              +260     *  <code>null</code> if none found or null throwable input
              +261     * @since 1.0
              +262     */
              +263    public static Throwable getCause(Throwable throwable) {
              +264        return getCause(throwable, CAUSE_METHOD_NAMES);
              +265    }
              +266
              +267    /**
              +268     * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
              +269     *
              +270     * <ol>
              +271     * <li>Try known exception types.</li>
              +272     * <li>Try the supplied array of method names.</li>
              +273     * <li>Try the field 'detail'.</li>
              +274     * </ol>
              +275     *
              +276     * <p>A <code>null</code> set of method names means use the default set.
              +277     * A <code>null</code> in the set of method names will be ignored.</p>
              +278     *
              +279     * @param throwable  the throwable to introspect for a cause, may be null
              +280     * @param methodNames  the method names, null treated as default set
              +281     * @return the cause of the <code>Throwable</code>,
              +282     *  <code>null</code> if none found or null throwable input
              +283     * @since 1.0
              +284     */
              +285    public static Throwable getCause(Throwable throwable, String[] methodNames) {
              +286        if (throwable == null) {
              +287            return null;
              +288        }
              +289        Throwable cause = getCauseUsingWellKnownTypes(throwable);
              +290        if (cause == null) {
              +291            if (methodNames == null) {
              +292                methodNames = CAUSE_METHOD_NAMES;
              +293            }
              +294            for (int i = 0; i < methodNames.length; i++) {
              +295                String methodName = methodNames[i];
              +296                if (methodName != null) {
              +297                    cause = getCauseUsingMethodName(throwable, methodName);
              +298                    if (cause != null) {
              +299                        break;
              +300                    }
              +301                }
              +302            }
              +303
              +304            if (cause == null) {
              +305                cause = getCauseUsingFieldName(throwable, "detail");
              +306            }
              +307        }
              +308        return cause;
              +309    }
              +310
              +311    /**
              +312     * <p>Introspects the <code>Throwable</code> to obtain the root cause.</p>
              +313     *
              +314     * <p>This method walks through the exception chain to the last element,
              +315     * "root" of the tree, using {@link #getCause(Throwable)}, and
              +316     * returns that exception.</p>
              +317     *
              +318     * <p>From version 2.2, this method handles recursive cause structures
              +319     * that might otherwise cause infinite loops. If the throwable parameter
              +320     * has a cause of itself, then null will be returned. If the throwable
              +321     * parameter cause chain loops, the last element in the chain before the
              +322     * loop is returned.</p>
              +323     *
              +324     * @param throwable  the throwable to get the root cause for, may be null
              +325     * @return the root cause of the <code>Throwable</code>,
              +326     *  <code>null</code> if none found or null throwable input
              +327     */
              +328    public static Throwable getRootCause(Throwable throwable) {
              +329        List list = getThrowableList(throwable);
              +330        return (list.size() < 2 ? null : (Throwable)list.get(list.size() - 1));
              +331    }
              +332
              +333    /**
              +334     * <p>Finds a <code>Throwable</code> for known types.</p>
              +335     *
              +336     * <p>Uses <code>instanceof</code> checks to examine the exception,
              +337     * looking for well known types which could contain chained or
              +338     * wrapped exceptions.</p>
              +339     *
              +340     * @param throwable  the exception to examine
              +341     * @return the wrapped exception, or <code>null</code> if not found
              +342     */
              +343    private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
              +344        if (throwable instanceof Nestable) {
              +345            return throwable.getCause();
              +346        } else if (throwable instanceof SQLException) {
              +347            return ((SQLException) throwable).getNextException();
              +348        } else if (throwable instanceof InvocationTargetException) {
              +349            return ((InvocationTargetException) throwable).getTargetException();
              +350        } else {
              +351            return null;
              +352        }
              +353    }
              +354
              +355    /**
              +356     * <p>Finds a <code>Throwable</code> by method name.</p>
              +357     *
              +358     * @param throwable  the exception to examine
              +359     * @param methodName  the name of the method to find and invoke
              +360     * @return the wrapped exception, or <code>null</code> if not found
              +361     */
              +362    private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName) {
              +363        Method method = null;
              +364        try {
              +365            method = throwable.getClass().getMethod(methodName, null);
              +366        } catch (NoSuchMethodException ignored) {
              +367            // exception ignored
              +368        } catch (SecurityException ignored) {
              +369            // exception ignored
              +370        }
              +371
              +372        if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
              +373            try {
              +374                return (Throwable) method.invoke(throwable);
              +375            } catch (IllegalAccessException ignored) {
              +376                // exception ignored
              +377            } catch (IllegalArgumentException ignored) {
              +378                // exception ignored
              +379            } catch (InvocationTargetException ignored) {
              +380                // exception ignored
              +381            }
              +382        }
              +383        return null;
              +384    }
              +385
              +386    /**
              +387     * <p>Finds a <code>Throwable</code> by field name.</p>
              +388     *
              +389     * @param throwable  the exception to examine
              +390     * @param fieldName  the name of the attribute to examine
              +391     * @return the wrapped exception, or <code>null</code> if not found
              +392     */
              +393    private static Throwable getCauseUsingFieldName(Throwable throwable, String fieldName) {
              +394        Field field = null;
              +395        try {
              +396            field = throwable.getClass().getField(fieldName);
              +397        } catch (NoSuchFieldException ignored) {
              +398            // exception ignored
              +399        } catch (SecurityException ignored) {
              +400            // exception ignored
              +401        }
              +402
              +403        if (field != null && Throwable.class.isAssignableFrom(field.getType())) {
              +404            try {
              +405                return (Throwable) field.get(throwable);
              +406            } catch (IllegalAccessException ignored) {
              +407                // exception ignored
              +408            } catch (IllegalArgumentException ignored) {
              +409                // exception ignored
              +410            }
              +411        }
              +412        return null;
              +413    }
              +414
              +415    //-----------------------------------------------------------------------
              +416    /**
              +417     * <p>Checks if the Throwable class has a <code>getCause</code> method.</p>
              +418     *
              +419     * <p>This is true for JDK 1.4 and above.</p>
              +420     *
              +421     * @return true if Throwable is nestable
              +422     * @since 2.0
              +423     */
              +424    public static boolean isThrowableNested() {
              +425        return THROWABLE_CAUSE_METHOD != null;
              +426    }
              +427
              +428    /**
              +429     * <p>Checks whether this <code>Throwable</code> class can store a cause.</p>
              +430     *
              +431     * <p>This method does <b>not</b> check whether it actually does store a cause.<p>
              +432     *
              +433     * @param throwable  the <code>Throwable</code> to examine, may be null
              +434     * @return boolean <code>true</code> if nested otherwise <code>false</code>
              +435     * @since 2.0
              +436     */
              +437    public static boolean isNestedThrowable(Throwable throwable) {
              +438        if (throwable == null) {
              +439            return false;
              +440        }
              +441
              +442        if (throwable instanceof Nestable) {
              +443            return true;
              +444        } else if (throwable instanceof SQLException) {
              +445            return true;
              +446        } else if (throwable instanceof InvocationTargetException) {
              +447            return true;
              +448        } else if (isThrowableNested()) {
              +449            return true;
              +450        }
              +451
              +452        Class cls = throwable.getClass();
              +453        for (int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++) {
              +454            try {
              +455                Method method = cls.getMethod(CAUSE_METHOD_NAMES[i], null);
              +456                if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
              +457                    return true;
              +458                }
              +459            } catch (NoSuchMethodException ignored) {
              +460                // exception ignored
              +461            } catch (SecurityException ignored) {
              +462                // exception ignored
              +463            }
              +464        }
              +465
              +466        try {
              +467            Field field = cls.getField("detail");
              +468            if (field != null) {
              +469                return true;
              +470            }
              +471        } catch (NoSuchFieldException ignored) {
              +472            // exception ignored
              +473        } catch (SecurityException ignored) {
              +474            // exception ignored
              +475        }
              +476
              +477        return false;
              +478    }
              +479
              +480    //-----------------------------------------------------------------------
              +481    /**
              +482     * <p>Counts the number of <code>Throwable</code> objects in the
              +483     * exception chain.</p>
              +484     *
              +485     * <p>A throwable without cause will return <code>1</code>.
              +486     * A throwable with one cause will return <code>2</code> and so on.
              +487     * A <code>null</code> throwable will return <code>0</code>.</p>
              +488     *
              +489     * <p>From version 2.2, this method handles recursive cause structures
              +490     * that might otherwise cause infinite loops. The cause chain is
              +491     * processed until the end is reached, or until the next item in the
              +492     * chain is already in the result set.</p>
              +493     *
              +494     * @param throwable  the throwable to inspect, may be null
              +495     * @return the count of throwables, zero if null input
              +496     */
              +497    public static int getThrowableCount(Throwable throwable) {
              +498        return getThrowableList(throwable).size();
              +499    }
              +500
              +501    /**
              +502     * <p>Returns the list of <code>Throwable</code> objects in the
              +503     * exception chain.</p>
              +504     *
              +505     * <p>A throwable without cause will return an array containing
              +506     * one element - the input throwable.
              +507     * A throwable with one cause will return an array containing
              +508     * two elements. - the input throwable and the cause throwable.
              +509     * A <code>null</code> throwable will return an array of size zero.</p>
              +510     *
              +511     * <p>From version 2.2, this method handles recursive cause structures
              +512     * that might otherwise cause infinite loops. The cause chain is
              +513     * processed until the end is reached, or until the next item in the
              +514     * chain is already in the result set.</p>
              +515     *
              +516     * @see #getThrowableList(Throwable)
              +517     * @param throwable  the throwable to inspect, may be null
              +518     * @return the array of throwables, never null
              +519     */
              +520    public static Throwable[] getThrowables(Throwable throwable) {
              +521        List list = getThrowableList(throwable);
              +522        return (Throwable[]) list.toArray(new Throwable[list.size()]);
              +523    }
              +524
              +525    /**
              +526     * <p>Returns the list of <code>Throwable</code> objects in the
              +527     * exception chain.</p>
              +528     *
              +529     * <p>A throwable without cause will return a list containing
              +530     * one element - the input throwable.
              +531     * A throwable with one cause will return a list containing
              +532     * two elements. - the input throwable and the cause throwable.
              +533     * A <code>null</code> throwable will return a list of size zero.</p>
              +534     *
              +535     * <p>This method handles recursive cause structures that might
              +536     * otherwise cause infinite loops. The cause chain is processed until
              +537     * the end is reached, or until the next item in the chain is already
              +538     * in the result set.</p>
              +539     *
              +540     * @param throwable  the throwable to inspect, may be null
              +541     * @return the list of throwables, never null
              +542     * @since Commons Lang 2.2
              +543     */
              +544    public static List getThrowableList(Throwable throwable) {
              +545        List list = new ArrayList();
              +546        while (throwable != null && list.contains(throwable) == false) {
              +547            list.add(throwable);
              +548            throwable = getCause(throwable);
              +549        }
              +550        return list;
              +551    }
              +552
              +553    //-----------------------------------------------------------------------
              +554    /**
              +555     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              +556     * that matches the specified class (exactly) in the exception chain.
              +557     * Subclasses of the specified class do not match - see
              +558     * {@link #indexOfType(Throwable, Class)} for the opposite.</p>
              +559     *
              +560     * <p>A <code>null</code> throwable returns <code>-1</code>.
              +561     * A <code>null</code> type returns <code>-1</code>.
              +562     * No match in the chain returns <code>-1</code>.</p>
              +563     *
              +564     * @param throwable  the throwable to inspect, may be null
              +565     * @param clazz  the class to search for, subclasses do not match, null returns -1
              +566     * @return the index into the throwable chain, -1 if no match or null input
              +567     */
              +568    public static int indexOfThrowable(Throwable throwable, Class clazz) {
              +569        return indexOf(throwable, clazz, 0, false);
              +570    }
              +571
              +572    /**
              +573     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              +574     * that matches the specified type in the exception chain from
              +575     * a specified index.
              +576     * Subclasses of the specified class do not match - see
              +577     * {@link #indexOfType(Throwable, Class, int)} for the opposite.</p>
              +578     *
              +579     * <p>A <code>null</code> throwable returns <code>-1</code>.
              +580     * A <code>null</code> type returns <code>-1</code>.
              +581     * No match in the chain returns <code>-1</code>.
              +582     * A negative start index is treated as zero.
              +583     * A start index greater than the number of throwables returns <code>-1</code>.</p>
              +584     *
              +585     * @param throwable  the throwable to inspect, may be null
              +586     * @param clazz  the class to search for, subclasses do not match, null returns -1
              +587     * @param fromIndex  the (zero based) index of the starting position,
              +588     *  negative treated as zero, larger than chain size returns -1
              +589     * @return the index into the throwable chain, -1 if no match or null input
              +590     */
              +591    public static int indexOfThrowable(Throwable throwable, Class clazz, int fromIndex) {
              +592        return indexOf(throwable, clazz, fromIndex, false);
              +593    }
              +594
              +595    //-----------------------------------------------------------------------
              +596    /**
              +597     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              +598     * that matches the specified class or subclass in the exception chain.
              +599     * Subclasses of the specified class do match - see
              +600     * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
              +601     *
              +602     * <p>A <code>null</code> throwable returns <code>-1</code>.
              +603     * A <code>null</code> type returns <code>-1</code>.
              +604     * No match in the chain returns <code>-1</code>.</p>
              +605     *
              +606     * @param throwable  the throwable to inspect, may be null
              +607     * @param type  the type to search for, subclasses match, null returns -1
              +608     * @return the index into the throwable chain, -1 if no match or null input
              +609     * @since 2.1
              +610     */
              +611    public static int indexOfType(Throwable throwable, Class type) {
              +612        return indexOf(throwable, type, 0, true);
              +613    }
              +614
              +615    /**
              +616     * <p>Returns the (zero based) index of the first <code>Throwable</code>
              +617     * that matches the specified type in the exception chain from
              +618     * a specified index.
              +619     * Subclasses of the specified class do match - see
              +620     * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
              +621     *
              +622     * <p>A <code>null</code> throwable returns <code>-1</code>.
              +623     * A <code>null</code> type returns <code>-1</code>.
              +624     * No match in the chain returns <code>-1</code>.
              +625     * A negative start index is treated as zero.
              +626     * A start index greater than the number of throwables returns <code>-1</code>.</p>
              +627     *
              +628     * @param throwable  the throwable to inspect, may be null
              +629     * @param type  the type to search for, subclasses match, null returns -1
              +630     * @param fromIndex  the (zero based) index of the starting position,
              +631     *  negative treated as zero, larger than chain size returns -1
              +632     * @return the index into the throwable chain, -1 if no match or null input
              +633     * @since 2.1
              +634     */
              +635    public static int indexOfType(Throwable throwable, Class type, int fromIndex) {
              +636        return indexOf(throwable, type, fromIndex, true);
              +637    }
              +638
              +639    /**
              +640     * <p>Worker method for the <code>indexOfType</code> methods.</p>
              +641     *
              +642     * @param throwable  the throwable to inspect, may be null
              +643     * @param type  the type to search for, subclasses match, null returns -1
              +644     * @param fromIndex  the (zero based) index of the starting position,
              +645     *  negative treated as zero, larger than chain size returns -1
              +646     * @param subclass if <code>true</code>, compares with {@link Class#isAssignableFrom(Class)}, otherwise compares
              +647     * using references
              +648     * @return index of the <code>type</code> within throwables nested withing the specified <code>throwable</code>
              +649     */
              +650    private static int indexOf(Throwable throwable, Class type, int fromIndex, boolean subclass) {
              +651        if (throwable == null || type == null) {
              +652            return -1;
              +653        }
              +654        if (fromIndex < 0) {
              +655            fromIndex = 0;
              +656        }
              +657        Throwable[] throwables = getThrowables(throwable);
              +658        if (fromIndex >= throwables.length) {
              +659            return -1;
              +660        }
              +661        if (subclass) {
              +662            for (int i = fromIndex; i < throwables.length; i++) {
              +663                if (type.isAssignableFrom(throwables[i].getClass())) {
              +664                    return i;
              +665                }
              +666            }
              +667        } else {
              +668            for (int i = fromIndex; i < throwables.length; i++) {
              +669                if (type.equals(throwables[i].getClass())) {
              +670                    return i;
              +671                }
              +672            }
              +673        }
              +674        return -1;
              +675    }
              +676
              +677    /**
              +678     * <p>Removes common frames from the cause trace given the two stack traces.</p>
              +679     *
              +680     * @param causeFrames  stack trace of a cause throwable
              +681     * @param wrapperFrames  stack trace of a wrapper throwable
              +682     * @throws IllegalArgumentException if either argument is null
              +683     * @since 2.0
              +684     */
              +685    public static void removeCommonFrames(List causeFrames, List wrapperFrames) {
              +686        if (causeFrames == null || wrapperFrames == null) {
              +687            throw new IllegalArgumentException("The List must not be null");
              +688        }
              +689        int causeFrameIndex = causeFrames.size() - 1;
              +690        int wrapperFrameIndex = wrapperFrames.size() - 1;
              +691        while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
              +692            // Remove the frame from the cause trace if it is the same
              +693            // as in the wrapper trace
              +694            String causeFrame = (String) causeFrames.get(causeFrameIndex);
              +695            String wrapperFrame = (String) wrapperFrames.get(wrapperFrameIndex);
              +696            if (causeFrame.equals(wrapperFrame)) {
              +697                causeFrames.remove(causeFrameIndex);
              +698            }
              +699            causeFrameIndex--;
              +700            wrapperFrameIndex--;
              +701        }
              +702    }
              +703
              +704    //-----------------------------------------------------------------------
              +705    /**
              +706     * <p>A way to get the entire nested stack-trace of an throwable.</p>
              +707     *
              +708     * <p>The result of this method is highly dependent on the JDK version
              +709     * and whether the exceptions override printStackTrace or not.</p>
              +710     *
              +711     * @param throwable  the <code>Throwable</code> to be examined
              +712     * @return the nested stack trace, with the root cause first
              +713     * @since 2.0
              +714     */
              +715    public static String getFullStackTrace(Throwable throwable) {
              +716        StringWriter sw = new StringWriter();
              +717        PrintWriter pw = new PrintWriter(sw, true);
              +718        Throwable[] ts = getThrowables(throwable);
              +719        for (int i = 0; i < ts.length; i++) {
              +720            ts[i].printStackTrace(pw);
              +721            if (isNestedThrowable(ts[i])) {
              +722                break;
              +723            }
              +724        }
              +725        return sw.getBuffer().toString();
              +726    }
              +727
              +728    //-----------------------------------------------------------------------
              +729    /**
              +730     * <p>Gets the stack trace from a Throwable as a String.</p>
              +731     *
              +732     * <p>The result of this method vary by JDK version as this method
              +733     * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
              +734     * On JDK1.3 and earlier, the cause exception will not be shown
              +735     * unless the specified throwable alters printStackTrace.</p>
              +736     *
              +737     * @param throwable  the <code>Throwable</code> to be examined
              +738     * @return the stack trace as generated by the exception's
              +739     *  <code>printStackTrace(PrintWriter)</code> method
              +740     */
              +741    public static String getStackTrace(Throwable throwable) {
              +742        StringWriter sw = new StringWriter();
              +743        PrintWriter pw = new PrintWriter(sw, true);
              +744        throwable.printStackTrace(pw);
              +745        return sw.getBuffer().toString();
              +746    }
              +747
              +748    /**
              +749     * <p>Captures the stack trace associated with the specified
              +750     * <code>Throwable</code> object, decomposing it into a list of
              +751     * stack frames.</p>
              +752     *
              +753     * <p>The result of this method vary by JDK version as this method
              +754     * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
              +755     * On JDK1.3 and earlier, the cause exception will not be shown
              +756     * unless the specified throwable alters printStackTrace.</p>
              +757     *
              +758     * @param throwable  the <code>Throwable</code> to examine, may be null
              +759     * @return an array of strings describing each stack frame, never null
              +760     */
              +761//    public static String[] getStackFrames(Throwable throwable) {
              +762//        if (throwable == null) {
              +763//            return ArrayUtils.EMPTY_STRING_ARRAY;
              +764//        }
              +765//        return getStackFrames(getStackTrace(throwable));
              +766//    }
              +767
              +768    //-----------------------------------------------------------------------
              +769    /**
              +770     * <p>Returns an array where each element is a line from the argument.</p>
              +771     *
              +772     * <p>The end of line is determined by the value of {@link SystemUtils#LINE_SEPARATOR}.</p>
              +773     *
              +774     * <p>Functionality shared between the
              +775     * <code>getStackFrames(Throwable)</code> methods of this and the
              +776     * {@link org.apache.commons.lang.exception.NestableDelegate} classes.</p>
              +777     *
              +778     * @param stackTrace  a stack trace String
              +779     * @return an array where each element is a line from the argument
              +780     */
              +781//    static String[] getStackFrames(String stackTrace) {
              +782//        String linebreak = SystemUtils.LINE_SEPARATOR;
              +783//        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
              +784//        List list = new ArrayList();
              +785//        while (frames.hasMoreTokens()) {
              +786//            list.add(frames.nextToken());
              +787//        }
              +788//        return toArray(list);
              +789//    }
              +790
              +791    /**
              +792     * <p>Produces a <code>List</code> of stack frames - the message
              +793     * is not included. Only the trace of the specified exception is
              +794     * returned, any caused by trace is stripped.</p>
              +795     *
              +796     * <p>This works in most cases - it will only fail if the exception
              +797     * message contains a line that starts with:
              +798     * <code>&quot;&nbsp;&nbsp;&nbsp;at&quot;.</code></p>
              +799     *
              +800     * @param t is any throwable
              +801     * @return List of stack frames
              +802     */
              +803    static List getStackFrameList(Throwable t) {
              +804        String stackTrace = getStackTrace(t);
              +805        String linebreak = LINE_SEPARATOR;
              +806        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
              +807        List list = new ArrayList();
              +808        boolean traceStarted = false;
              +809        while (frames.hasMoreTokens()) {
              +810            String token = frames.nextToken();
              +811            // Determine if the line starts with <whitespace>at
              +812            int at = token.indexOf("at");
              +813            if (at != -1 && token.substring(0, at).trim().length() == 0) {
              +814                traceStarted = true;
              +815                list.add(token);
              +816            } else if (traceStarted) {
              +817                break;
              +818            }
              +819        }
              +820        return list;
              +821    }
              +822
              +823    //-----------------------------------------------------------------------
              +824    /**
              +825     * Gets a short message summarising the exception.
              +826     * <p>
              +827     * The message returned is of the form
              +828     * {ClassNameWithoutPackage}: {ThrowableMessage}
              +829     *
              +830     * @param th  the throwable to get a message for, null returns empty string
              +831     * @return the message, non-null
              +832     * @since Commons Lang 2.2
              +833     */
              +834//    public static String getMessage(Throwable th) {
              +835//        if (th == null) {
              +836//            return "";
              +837//        }
              +838//        String clsName = ClassUtils.getShortClassName(th, null);
              +839//        String msg = th.getMessage();
              +840//        return clsName + ": " + StringUtils.defaultString(msg);
              +841//    }
              +842
              +843    //-----------------------------------------------------------------------
              +844    /**
              +845     * Gets a short message summarising the root cause exception.
              +846     * <p>
              +847     * The message returned is of the form
              +848     * {ClassNameWithoutPackage}: {ThrowableMessage}
              +849     *
              +850     * @param th  the throwable to get a message for, null returns empty string
              +851     * @return the message, non-null
              +852     * @since Commons Lang 2.2
              +853     */
              +854//    public static String getRootCauseMessage(Throwable th) {
              +855//        Throwable root = ExceptionUtils.getRootCause(th);
              +856//        root = (root == null ? th : root);
              +857//        return getMessage(root);
              +858//    }
              +859
              +860    /**
              +861     * An interface to be implemented by {@link java.lang.Throwable}
              +862     * extensions which would like to be able to nest root exceptions
              +863     * inside themselves.
              +864     *
              +865     * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
              +866     * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
              +867     * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
              +868     * @author Pete Gieser
              +869     * @since 1.0
              +870     * @version $Id$
              +871     */
              +872    public interface Nestable {
              +873
              +874        /**
              +875         * Returns the reference to the exception or error that caused the
              +876         * exception implementing the <code>Nestable</code> to be thrown.
              +877         *
              +878         * @return throwable that caused the original exception
              +879         */
              +880        Throwable getCause();
              +881
              +882        /**
              +883         * Returns the error message of this and any nested
              +884         * <code>Throwable</code>.
              +885         *
              +886         * @return the error message
              +887         */
              +888        String getMessage();
              +889
              +890        /**
              +891         * Returns the error message of the <code>Throwable</code> in the chain
              +892         * of <code>Throwable</code>s at the specified index, numbered from 0.
              +893         *
              +894         * @param index the index of the <code>Throwable</code> in the chain of
              +895         * <code>Throwable</code>s
              +896         * @return the error message, or null if the <code>Throwable</code> at the
              +897         * specified index in the chain does not contain a message
              +898         * @throws IndexOutOfBoundsException if the <code>index</code> argument is
              +899         * negative or not less than the count of <code>Throwable</code>s in the
              +900         * chain
              +901         */
              +902        String getMessage(int index);
              +903
              +904        /**
              +905         * Returns the error message of this and any nested <code>Throwable</code>s
              +906         * in an array of Strings, one element for each message. Any
              +907         * <code>Throwable</code> not containing a message is represented in the
              +908         * array by a null. This has the effect of cause the length of the returned
              +909         * array to be equal to the result of the {@link #getThrowableCount()}
              +910         * operation.
              +911         *
              +912         * @return the error messages
              +913         */
              +914        String[] getMessages();
              +915
              +916        /**
              +917         * Returns the <code>Throwable</code> in the chain of
              +918         * <code>Throwable</code>s at the specified index, numbered from 0.
              +919         *
              +920         * @param index the index, numbered from 0, of the <code>Throwable</code> in
              +921         * the chain of <code>Throwable</code>s
              +922         * @return the <code>Throwable</code>
              +923         * @throws IndexOutOfBoundsException if the <code>index</code> argument is
              +924         * negative or not less than the count of <code>Throwable</code>s in the
              +925         * chain
              +926         */
              +927        Throwable getThrowable(int index);
              +928
              +929        /**
              +930         * Returns the number of nested <code>Throwable</code>s represented by
              +931         * this <code>Nestable</code>, including this <code>Nestable</code>.
              +932         *
              +933         * @return the throwable count
              +934         */
              +935        int getThrowableCount();
              +936
              +937        /**
              +938         * Returns this <code>Nestable</code> and any nested <code>Throwable</code>s
              +939         * in an array of <code>Throwable</code>s, one element for each
              +940         * <code>Throwable</code>.
              +941         *
              +942         * @return the <code>Throwable</code>s
              +943         */
              +944        Throwable[] getThrowables();
              +945
              +946        /**
              +947         * Returns the index, numbered from 0, of the first occurrence of the
              +948         * specified type, or a subclass, in the chain of <code>Throwable</code>s.
              +949         * The method returns -1 if the specified type is not found in the chain.
              +950         * <p>
              +951         * NOTE: From v2.1, we have clarified the <code>Nestable</code> interface
              +952         * such that this method matches subclasses.
              +953         * If you want to NOT match subclasses, please use
              +954         * (which is avaiable in all versions of lang).
              +955         *
              +956         * @param type  the type to find, subclasses match, null returns -1
              +957         * @return index of the first occurrence of the type in the chain, or -1 if
              +958         * the type is not found
              +959         */
              +960        int indexOfThrowable(Class type);
              +961
              +962        /**
              +963         * Returns the index, numbered from 0, of the first <code>Throwable</code>
              +964         * that matches the specified type, or a subclass, in the chain of <code>Throwable</code>s
              +965         * with an index greater than or equal to the specified index.
              +966         * The method returns -1 if the specified type is not found in the chain.
              +967         * <p>
              +968         * NOTE: From v2.1, we have clarified the <code>Nestable</code> interface
              +969         * such that this method matches subclasses.
              +970         * If you want to NOT match subclasses, please use
              +971         * (which is avaiable in all versions of lang).
              +972         *
              +973         * @param type  the type to find, subclasses match, null returns -1
              +974         * @param fromIndex the index, numbered from 0, of the starting position in
              +975         * the chain to be searched
              +976         * @return index of the first occurrence of the type in the chain, or -1 if
              +977         * the type is not found
              +978         * @throws IndexOutOfBoundsException if the <code>fromIndex</code> argument
              +979         * is negative or not less than the count of <code>Throwable</code>s in the
              +980         * chain
              +981         */
              +982        int indexOfThrowable(Class type, int fromIndex);
              +983
              +984        /**
              +985         * Prints the stack trace of this exception to the specified print
              +986         * writer.  Includes information from the exception, if any,
              +987         * which caused this exception.
              +988         *
              +989         * @param out <code>PrintWriter</code> to use for output.
              +990         */
              +991        void printStackTrace(PrintWriter out);
              +992
              +993        /**
              +994         * Prints the stack trace of this exception to the specified print
              +995         * stream.  Includes information from the exception, if any,
              +996         * which caused this exception.
              +997         *
              +998         * @param out <code>PrintStream</code> to use for output.
              +999         */
              +1000        void printStackTrace(PrintStream out);
              +1001
              +1002        /**
              +1003         * Prints the stack trace for this exception only--root cause not
              +1004         * included--using the provided writer.  Used by
              +1005         * individual stack traces to a buffer.  The implementation of
              +1006         * this method should call
              +1007         * <code>super.printStackTrace(out);</code> in most cases.
              +1008         *
              +1009         * @param out The writer to use.
              +1010         */
              +1011        void printPartialStackTrace(PrintWriter out);
              +1012
              +1013    }
              +1014}
               
               
               
              @@ -1082,5 +1083,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsLangUtil.html b/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsLangUtil.html index 3342d067..0a9f24ba 100644 --- a/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsLangUtil.html +++ b/docs/acf-core/src-html/co/aikar/commands/apachecommonslang/ApacheCommonsLangUtil.html @@ -1,1410 +1,1412 @@ - + Source code +
              -
              001/*
              -002* Licensed to the Apache Software Foundation (ASF) under one or more
              -003* contributor license agreements.  See the NOTICE file distributed with
              -004* this work for additional information regarding copyright ownership.
              -005* The ASF licenses this file to You under the Apache License, Version 2.0
              -006* (the "License"); you may not use this file except in compliance with
              -007* the License.  You may obtain a copy of the License at
              -008*
              -009*      http://www.apache.org/licenses/LICENSE-2.0
              -010*
              -011* Unless required by applicable law or agreed to in writing, software
              -012* distributed under the License is distributed on an "AS IS" BASIS,
              -013* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
              -014* See the License for the specific language governing permissions and
              -015* limitations under the License.
              -016*/
              -017
              -018package co.aikar.commands.apachecommonslang;
              -019
              -020import java.lang.reflect.Array;
              -021import java.util.Iterator;
              -022
              -023/**
              -024 * Select methods copied from Apache Commons to avoid importing entire lib
              -025 * No changes to logic
              -026 */
              -027public class ApacheCommonsLangUtil {
              -028
              -029    /**
              -030     * The empty String {@code ""}.
              -031     * @since 2.0
              -032     */
              -033    public static final String EMPTY = "";
              -034    /**
              -035     * <p>Shallow clones an array returning a typecast result and handling
              -036     * {@code null}.
              -037     *
              -038     * <p>The objects in the array are not cloned, thus there is no special
              -039     * handling for multi-dimensional arrays.
              -040     *
              -041     * <p>This method returns {@code null} for a {@code null} input array.
              -042     *
              -043     * @param <T> the component type of the array
              -044     * @param array  the array to shallow clone, may be {@code null}
              -045     * @return the cloned array, {@code null} if {@code null} input
              -046     */
              -047    public static <T> T[] clone(final T[] array) {
              -048        if (array == null) {
              -049            return null;
              -050        }
              -051        return array.clone();
              -052    }
              -053
              -054    /**
              -055     * <p>Adds all the elements of the given arrays into a new array.
              -056     * <p>The new array contains all of the element of {@code array1} followed
              -057     * by all of the elements {@code array2}. When an array is returned, it is always
              -058     * a new array.
              -059     *
              -060     * <pre>
              -061     * ArrayUtils.addAll(null, null)     = null
              -062     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
              -063     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
              -064     * ArrayUtils.addAll([], [])         = []
              -065     * ArrayUtils.addAll([null], [null]) = [null, null]
              -066     * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
              -067     * </pre>
              -068     *
              -069     * @param <T> the component type of the array
              -070     * @param array1  the first array whose elements are added to the new array, may be {@code null}
              -071     * @param array2  the second array whose elements are added to the new array, may be {@code null}
              -072     * @return The new array, {@code null} if both arrays are {@code null}.
              -073     *      The type of the new array is the type of the first array,
              -074     *      unless the first array is null, in which case the type is the same as the second array.
              -075     * @since 2.1
              -076     * @throws IllegalArgumentException if the array types are incompatible
              -077     */
              -078    public static <T> T[] addAll(final T[] array1, final T... array2) {
              -079        if (array1 == null) {
              -080            return clone(array2);
              -081        } else if (array2 == null) {
              -082            return clone(array1);
              -083        }
              -084        final Class<?> type1 = array1.getClass().getComponentType();
              -085        @SuppressWarnings("unchecked") // OK, because array is of type T
              -086        final T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
              -087        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
              -088        try {
              -089            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
              -090        } catch (final ArrayStoreException ase) {
              -091            // Check if problem was due to incompatible types
              -092            /*
              -093             * We do this here, rather than before the copy because:
              -094             * - it would be a wasted check most of the time
              -095             * - safer, in case check turns out to be too strict
              -096             */
              -097            final Class<?> type2 = array2.getClass().getComponentType();
              -098            if (!type1.isAssignableFrom(type2)) {
              -099                throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
              -100                        + type1.getName(), ase);
              -101            }
              -102            throw ase; // No, so rethrow original
              -103        }
              -104        return joinedArray;
              -105    }
              -106
              -107    //-----------------------------------------------------------------------
              -108    /**
              -109     * <p>Converts all the whitespace separated words in a String into capitalized words,
              -110     * that is each word is made up of a titlecase character and then a series of
              -111     * lowercase characters.  </p>
              -112     *
              -113     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
              -114     * A <code>null</code> input String returns <code>null</code>.
              -115     * Capitalization uses the Unicode title case, normally equivalent to
              -116     * upper case.</p>
              -117     *
              -118     * <pre>
              -119     * WordUtils.capitalizeFully(null)        = null
              -120     * WordUtils.capitalizeFully("")          = ""
              -121     * WordUtils.capitalizeFully("i am FINE") = "I Am Fine"
              -122     * </pre>
              -123     *
              -124     * @param str  the String to capitalize, may be null
              -125     * @return capitalized String, <code>null</code> if null String input
              -126     */
              -127    public static String capitalizeFully(final String str) {
              -128        return capitalizeFully(str, null);
              -129    }
              -130
              -131    /**
              -132     * <p>Converts all the delimiter separated words in a String into capitalized words,
              -133     * that is each word is made up of a titlecase character and then a series of
              -134     * lowercase characters. </p>
              -135     *
              -136     * <p>The delimiters represent a set of characters understood to separate words.
              -137     * The first string character and the first non-delimiter character after a
              -138     * delimiter will be capitalized. </p>
              -139     *
              -140     * <p>A <code>null</code> input String returns <code>null</code>.
              -141     * Capitalization uses the Unicode title case, normally equivalent to
              -142     * upper case.</p>
              -143     *
              -144     * <pre>
              -145     * WordUtils.capitalizeFully(null, *)            = null
              -146     * WordUtils.capitalizeFully("", *)              = ""
              -147     * WordUtils.capitalizeFully(*, null)            = *
              -148     * WordUtils.capitalizeFully(*, new char[0])     = *
              -149     * WordUtils.capitalizeFully("i aM.fine", {'.'}) = "I am.Fine"
              -150     * </pre>
              -151     *
              -152     * @param str  the String to capitalize, may be null
              -153     * @param delimiters  set of characters to determine capitalization, null means whitespace
              -154     * @return capitalized String, <code>null</code> if null String input
              -155     * @since 2.1
              -156     */
              -157    public static String capitalizeFully(String str, final char... delimiters) {
              -158        final int delimLen = delimiters == null ? -1 : delimiters.length;
              -159        if (str == null || str.isEmpty() || delimLen == 0) {
              -160            return str;
              -161        }
              -162        str = str.toLowerCase();
              -163        return capitalize(str, delimiters);
              -164    }
              -165
              -166    // Capitalizing
              -167    //-----------------------------------------------------------------------
              -168    /**
              -169     * <p>Capitalizes all the whitespace separated words in a String.
              -170     * Only the first character of each word is changed. To convert the
              -171     * rest of each word to lowercase at the same time,
              -172     * use {@link #capitalizeFully(String)}.</p>
              -173     *
              -174     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
              -175     * A <code>null</code> input String returns <code>null</code>.
              -176     * Capitalization uses the Unicode title case, normally equivalent to
              -177     * upper case.</p>
              -178     *
              -179     * <pre>
              -180     * WordUtils.capitalize(null)        = null
              -181     * WordUtils.capitalize("")          = ""
              -182     * WordUtils.capitalize("i am FINE") = "I Am FINE"
              -183     * </pre>
              -184     *
              -185     * @param str  the String to capitalize, may be null
              -186     * @return capitalized String, <code>null</code> if null String input
              -187     * @see #capitalizeFully(String)
              -188     */
              -189    public static String capitalize(final String str) {
              -190        return capitalize(str, null);
              -191    }
              -192
              -193    /**
              -194     * <p>Capitalizes all the delimiter separated words in a String.
              -195     * Only the first character of each word is changed. To convert the
              -196     * rest of each word to lowercase at the same time,
              -197     * use {@link #capitalizeFully(String, char[])}.</p>
              -198     *
              -199     * <p>The delimiters represent a set of characters understood to separate words.
              -200     * The first string character and the first non-delimiter character after a
              -201     * delimiter will be capitalized. </p>
              -202     *
              -203     * <p>A <code>null</code> input String returns <code>null</code>.
              -204     * Capitalization uses the Unicode title case, normally equivalent to
              -205     * upper case.</p>
              -206     *
              -207     * <pre>
              -208     * WordUtils.capitalize(null, *)            = null
              -209     * WordUtils.capitalize("", *)              = ""
              -210     * WordUtils.capitalize(*, new char[0])     = *
              -211     * WordUtils.capitalize("i am fine", null)  = "I Am Fine"
              -212     * WordUtils.capitalize("i aM.fine", {'.'}) = "I aM.Fine"
              -213     * </pre>
              -214     *
              -215     * @param str  the String to capitalize, may be null
              -216     * @param delimiters  set of characters to determine capitalization, null means whitespace
              -217     * @return capitalized String, <code>null</code> if null String input
              -218     * @see #capitalizeFully(String)
              -219     * @since 2.1
              -220     */
              -221    public static String capitalize(final String str, final char... delimiters) {
              -222        final int delimLen = delimiters == null ? -1 : delimiters.length;
              -223        if (str == null || str.isEmpty() || delimLen == 0) {
              -224            return str;
              -225        }
              -226        final char[] buffer = str.toCharArray();
              -227        boolean capitalizeNext = true;
              -228        for (int i = 0; i < buffer.length; i++) {
              -229            final char ch = buffer[i];
              -230            if (isDelimiter(ch, delimiters)) {
              -231                capitalizeNext = true;
              -232            } else if (capitalizeNext) {
              -233                buffer[i] = Character.toTitleCase(ch);
              -234                capitalizeNext = false;
              -235            }
              -236        }
              -237        return new String(buffer);
              -238    }
              -239    //-----------------------------------------------------------------------
              -240    /**
              -241     * Is the character a delimiter.
              -242     *
              -243     * @param ch  the character to check
              -244     * @param delimiters  the delimiters
              -245     * @return true if it is a delimiter
              -246     */
              -247    public static boolean isDelimiter(final char ch, final char[] delimiters) {
              -248        if (delimiters == null) {
              -249            return Character.isWhitespace(ch);
              -250        }
              -251        for (final char delimiter : delimiters) {
              -252            if (ch == delimiter) {
              -253                return true;
              -254            }
              -255        }
              -256        return false;
              -257    }
              -258
              -259    // Joining
              -260    //-----------------------------------------------------------------------
              -261    /**
              -262     * <p>Joins the elements of the provided array into a single String
              -263     * containing the provided list of elements.</p>
              -264     *
              -265     * <p>No separator is added to the joined String.
              -266     * Null objects or empty strings within the array are represented by
              -267     * empty strings.</p>
              -268     *
              -269     * <pre>
              -270     * StringUtils.join(null)            = null
              -271     * StringUtils.join([])              = ""
              -272     * StringUtils.join([null])          = ""
              -273     * StringUtils.join(["a", "b", "c"]) = "abc"
              -274     * StringUtils.join([null, "", "a"]) = "a"
              -275     * </pre>
              -276     *
              -277     * @param <T> the specific type of values to join together
              -278     * @param elements  the values to join together, may be null
              -279     * @return the joined String, {@code null} if null array input
              -280     * @since 2.0
              -281     * @since 3.0 Changed signature to use varargs
              -282     */
              -283    @SafeVarargs
              -284    public static <T> String join(final T... elements) {
              -285        return join(elements, null);
              -286    }
              -287
              -288    /**
              -289     * <p>Joins the elements of the provided array into a single String
              -290     * containing the provided list of elements.</p>
              -291     *
              -292     * <p>No delimiter is added before or after the list.
              -293     * Null objects or empty strings within the array are represented by
              -294     * empty strings.</p>
              -295     *
              -296     * <pre>
              -297     * StringUtils.join(null, *)               = null
              -298     * StringUtils.join([], *)                 = ""
              -299     * StringUtils.join([null], *)             = ""
              -300     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
              -301     * StringUtils.join(["a", "b", "c"], null) = "abc"
              -302     * StringUtils.join([null, "", "a"], ';')  = ";;a"
              -303     * </pre>
              -304     *
              -305     * @param array  the array of values to join together, may be null
              -306     * @param separator  the separator character to use
              -307     * @return the joined String, {@code null} if null array input
              -308     * @since 2.0
              -309     */
              -310    public static String join(final Object[] array, final char separator) {
              -311        if (array == null) {
              -312            return null;
              -313        }
              -314        return join(array, separator, 0, array.length);
              -315    }
              -316
              -317    /**
              -318     * <p>
              -319     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -320     * </p>
              -321     *
              -322     * <p>
              -323     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -324     * by empty strings.
              -325     * </p>
              -326     *
              -327     * <pre>
              -328     * StringUtils.join(null, *)               = null
              -329     * StringUtils.join([], *)                 = ""
              -330     * StringUtils.join([null], *)             = ""
              -331     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -332     * StringUtils.join([1, 2, 3], null) = "123"
              -333     * </pre>
              -334     *
              -335     * @param array
              -336     *            the array of values to join together, may be null
              -337     * @param separator
              -338     *            the separator character to use
              -339     * @return the joined String, {@code null} if null array input
              -340     * @since 3.2
              -341     */
              -342    public static String join(final long[] array, final char separator) {
              -343        if (array == null) {
              -344            return null;
              -345        }
              -346        return join(array, separator, 0, array.length);
              -347    }
              -348
              -349    /**
              -350     * <p>
              -351     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -352     * </p>
              -353     *
              -354     * <p>
              -355     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -356     * by empty strings.
              -357     * </p>
              -358     *
              -359     * <pre>
              -360     * StringUtils.join(null, *)               = null
              -361     * StringUtils.join([], *)                 = ""
              -362     * StringUtils.join([null], *)             = ""
              -363     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -364     * StringUtils.join([1, 2, 3], null) = "123"
              -365     * </pre>
              -366     *
              -367     * @param array
              -368     *            the array of values to join together, may be null
              -369     * @param separator
              -370     *            the separator character to use
              -371     * @return the joined String, {@code null} if null array input
              -372     * @since 3.2
              -373     */
              -374    public static String join(final int[] array, final char separator) {
              -375        if (array == null) {
              -376            return null;
              -377        }
              -378        return join(array, separator, 0, array.length);
              -379    }
              -380
              -381    /**
              -382     * <p>
              -383     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -384     * </p>
              -385     *
              -386     * <p>
              -387     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -388     * by empty strings.
              -389     * </p>
              -390     *
              -391     * <pre>
              -392     * StringUtils.join(null, *)               = null
              -393     * StringUtils.join([], *)                 = ""
              -394     * StringUtils.join([null], *)             = ""
              -395     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -396     * StringUtils.join([1, 2, 3], null) = "123"
              -397     * </pre>
              -398     *
              -399     * @param array
              -400     *            the array of values to join together, may be null
              -401     * @param separator
              -402     *            the separator character to use
              -403     * @return the joined String, {@code null} if null array input
              -404     * @since 3.2
              -405     */
              -406    public static String join(final short[] array, final char separator) {
              -407        if (array == null) {
              -408            return null;
              -409        }
              -410        return join(array, separator, 0, array.length);
              -411    }
              -412
              -413    /**
              -414     * <p>
              -415     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -416     * </p>
              -417     *
              -418     * <p>
              -419     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -420     * by empty strings.
              -421     * </p>
              -422     *
              -423     * <pre>
              -424     * StringUtils.join(null, *)               = null
              -425     * StringUtils.join([], *)                 = ""
              -426     * StringUtils.join([null], *)             = ""
              -427     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -428     * StringUtils.join([1, 2, 3], null) = "123"
              -429     * </pre>
              -430     *
              -431     * @param array
              -432     *            the array of values to join together, may be null
              -433     * @param separator
              -434     *            the separator character to use
              -435     * @return the joined String, {@code null} if null array input
              -436     * @since 3.2
              -437     */
              -438    public static String join(final byte[] array, final char separator) {
              -439        if (array == null) {
              -440            return null;
              -441        }
              -442        return join(array, separator, 0, array.length);
              -443    }
              -444
              -445    /**
              -446     * <p>
              -447     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -448     * </p>
              -449     *
              -450     * <p>
              -451     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -452     * by empty strings.
              -453     * </p>
              -454     *
              -455     * <pre>
              -456     * StringUtils.join(null, *)               = null
              -457     * StringUtils.join([], *)                 = ""
              -458     * StringUtils.join([null], *)             = ""
              -459     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -460     * StringUtils.join([1, 2, 3], null) = "123"
              -461     * </pre>
              -462     *
              -463     * @param array
              -464     *            the array of values to join together, may be null
              -465     * @param separator
              -466     *            the separator character to use
              -467     * @return the joined String, {@code null} if null array input
              -468     * @since 3.2
              -469     */
              -470    public static String join(final char[] array, final char separator) {
              -471        if (array == null) {
              -472            return null;
              -473        }
              -474        return join(array, separator, 0, array.length);
              -475    }
              -476
              -477    /**
              -478     * <p>
              -479     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -480     * </p>
              -481     *
              -482     * <p>
              -483     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -484     * by empty strings.
              -485     * </p>
              -486     *
              -487     * <pre>
              -488     * StringUtils.join(null, *)               = null
              -489     * StringUtils.join([], *)                 = ""
              -490     * StringUtils.join([null], *)             = ""
              -491     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -492     * StringUtils.join([1, 2, 3], null) = "123"
              -493     * </pre>
              -494     *
              -495     * @param array
              -496     *            the array of values to join together, may be null
              -497     * @param separator
              -498     *            the separator character to use
              -499     * @return the joined String, {@code null} if null array input
              -500     * @since 3.2
              -501     */
              -502    public static String join(final float[] array, final char separator) {
              -503        if (array == null) {
              -504            return null;
              -505        }
              -506        return join(array, separator, 0, array.length);
              -507    }
              -508
              -509    /**
              -510     * <p>
              -511     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -512     * </p>
              -513     *
              -514     * <p>
              -515     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -516     * by empty strings.
              -517     * </p>
              -518     *
              -519     * <pre>
              -520     * StringUtils.join(null, *)               = null
              -521     * StringUtils.join([], *)                 = ""
              -522     * StringUtils.join([null], *)             = ""
              -523     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -524     * StringUtils.join([1, 2, 3], null) = "123"
              -525     * </pre>
              -526     *
              -527     * @param array
              -528     *            the array of values to join together, may be null
              -529     * @param separator
              -530     *            the separator character to use
              -531     * @return the joined String, {@code null} if null array input
              -532     * @since 3.2
              -533     */
              -534    public static String join(final double[] array, final char separator) {
              -535        if (array == null) {
              -536            return null;
              -537        }
              -538        return join(array, separator, 0, array.length);
              -539    }
              -540
              -541
              -542    /**
              -543     * <p>Joins the elements of the provided array into a single String
              -544     * containing the provided list of elements.</p>
              -545     *
              -546     * <p>No delimiter is added before or after the list.
              -547     * Null objects or empty strings within the array are represented by
              -548     * empty strings.</p>
              -549     *
              -550     * <pre>
              -551     * StringUtils.join(null, *)               = null
              -552     * StringUtils.join([], *)                 = ""
              -553     * StringUtils.join([null], *)             = ""
              -554     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
              -555     * StringUtils.join(["a", "b", "c"], null) = "abc"
              -556     * StringUtils.join([null, "", "a"], ';')  = ";;a"
              -557     * </pre>
              -558     *
              -559     * @param array  the array of values to join together, may be null
              -560     * @param separator  the separator character to use
              -561     * @param startIndex the first index to start joining from.  It is
              -562     * an error to pass in an end index past the end of the array
              -563     * @param endIndex the index to stop joining from (exclusive). It is
              -564     * an error to pass in an end index past the end of the array
              -565     * @return the joined String, {@code null} if null array input
              -566     * @since 2.0
              -567     */
              -568    public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) {
              -569        if (array == null) {
              -570            return null;
              -571        }
              -572        final int noOfItems = endIndex - startIndex;
              -573        if (noOfItems <= 0) {
              -574            return EMPTY;
              -575        }
              -576        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              -577        for (int i = startIndex; i < endIndex; i++) {
              -578            if (i > startIndex) {
              -579                buf.append(separator);
              -580            }
              -581            if (array[i] != null) {
              -582                buf.append(array[i]);
              -583            }
              -584        }
              -585        return buf.toString();
              -586    }
              -587
              -588    /**
              -589     * <p>
              -590     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -591     * </p>
              -592     *
              -593     * <p>
              -594     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -595     * by empty strings.
              -596     * </p>
              -597     *
              -598     * <pre>
              -599     * StringUtils.join(null, *)               = null
              -600     * StringUtils.join([], *)                 = ""
              -601     * StringUtils.join([null], *)             = ""
              -602     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -603     * StringUtils.join([1, 2, 3], null) = "123"
              -604     * </pre>
              -605     *
              -606     * @param array
              -607     *            the array of values to join together, may be null
              -608     * @param separator
              -609     *            the separator character to use
              -610     * @param startIndex
              -611     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              -612     *            array
              -613     * @param endIndex
              -614     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              -615     *            the array
              -616     * @return the joined String, {@code null} if null array input
              -617     * @since 3.2
              -618     */
              -619    public static String join(final long[] array, final char separator, final int startIndex, final int endIndex) {
              -620        if (array == null) {
              -621            return null;
              -622        }
              -623        final int noOfItems = endIndex - startIndex;
              -624        if (noOfItems <= 0) {
              -625            return EMPTY;
              -626        }
              -627        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              -628        for (int i = startIndex; i < endIndex; i++) {
              -629            if (i > startIndex) {
              -630                buf.append(separator);
              -631            }
              -632            buf.append(array[i]);
              -633        }
              -634        return buf.toString();
              -635    }
              -636
              -637    /**
              -638     * <p>
              -639     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -640     * </p>
              -641     *
              -642     * <p>
              -643     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -644     * by empty strings.
              -645     * </p>
              -646     *
              -647     * <pre>
              -648     * StringUtils.join(null, *)               = null
              -649     * StringUtils.join([], *)                 = ""
              -650     * StringUtils.join([null], *)             = ""
              -651     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -652     * StringUtils.join([1, 2, 3], null) = "123"
              -653     * </pre>
              -654     *
              -655     * @param array
              -656     *            the array of values to join together, may be null
              -657     * @param separator
              -658     *            the separator character to use
              -659     * @param startIndex
              -660     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              -661     *            array
              -662     * @param endIndex
              -663     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              -664     *            the array
              -665     * @return the joined String, {@code null} if null array input
              -666     * @since 3.2
              -667     */
              -668    public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) {
              -669        if (array == null) {
              -670            return null;
              -671        }
              -672        final int noOfItems = endIndex - startIndex;
              -673        if (noOfItems <= 0) {
              -674            return EMPTY;
              -675        }
              -676        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              -677        for (int i = startIndex; i < endIndex; i++) {
              -678            if (i > startIndex) {
              -679                buf.append(separator);
              -680            }
              -681            buf.append(array[i]);
              -682        }
              -683        return buf.toString();
              -684    }
              -685
              -686    /**
              -687     * <p>
              -688     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -689     * </p>
              -690     *
              -691     * <p>
              -692     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -693     * by empty strings.
              -694     * </p>
              -695     *
              -696     * <pre>
              -697     * StringUtils.join(null, *)               = null
              -698     * StringUtils.join([], *)                 = ""
              -699     * StringUtils.join([null], *)             = ""
              -700     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -701     * StringUtils.join([1, 2, 3], null) = "123"
              -702     * </pre>
              -703     *
              -704     * @param array
              -705     *            the array of values to join together, may be null
              -706     * @param separator
              -707     *            the separator character to use
              -708     * @param startIndex
              -709     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              -710     *            array
              -711     * @param endIndex
              -712     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              -713     *            the array
              -714     * @return the joined String, {@code null} if null array input
              -715     * @since 3.2
              -716     */
              -717    public static String join(final byte[] array, final char separator, final int startIndex, final int endIndex) {
              -718        if (array == null) {
              -719            return null;
              -720        }
              -721        final int noOfItems = endIndex - startIndex;
              -722        if (noOfItems <= 0) {
              -723            return EMPTY;
              -724        }
              -725        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              -726        for (int i = startIndex; i < endIndex; i++) {
              -727            if (i > startIndex) {
              -728                buf.append(separator);
              -729            }
              -730            buf.append(array[i]);
              -731        }
              -732        return buf.toString();
              -733    }
              -734
              -735    /**
              -736     * <p>
              -737     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -738     * </p>
              -739     *
              -740     * <p>
              -741     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -742     * by empty strings.
              -743     * </p>
              -744     *
              -745     * <pre>
              -746     * StringUtils.join(null, *)               = null
              -747     * StringUtils.join([], *)                 = ""
              -748     * StringUtils.join([null], *)             = ""
              -749     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -750     * StringUtils.join([1, 2, 3], null) = "123"
              -751     * </pre>
              -752     *
              -753     * @param array
              -754     *            the array of values to join together, may be null
              -755     * @param separator
              -756     *            the separator character to use
              -757     * @param startIndex
              -758     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              -759     *            array
              -760     * @param endIndex
              -761     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              -762     *            the array
              -763     * @return the joined String, {@code null} if null array input
              -764     * @since 3.2
              -765     */
              -766    public static String join(final short[] array, final char separator, final int startIndex, final int endIndex) {
              -767        if (array == null) {
              -768            return null;
              -769        }
              -770        final int noOfItems = endIndex - startIndex;
              -771        if (noOfItems <= 0) {
              -772            return EMPTY;
              -773        }
              -774        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              -775        for (int i = startIndex; i < endIndex; i++) {
              -776            if (i > startIndex) {
              -777                buf.append(separator);
              -778            }
              -779            buf.append(array[i]);
              -780        }
              -781        return buf.toString();
              -782    }
              -783
              -784    /**
              -785     * <p>
              -786     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -787     * </p>
              -788     *
              -789     * <p>
              -790     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -791     * by empty strings.
              -792     * </p>
              -793     *
              -794     * <pre>
              -795     * StringUtils.join(null, *)               = null
              -796     * StringUtils.join([], *)                 = ""
              -797     * StringUtils.join([null], *)             = ""
              -798     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -799     * StringUtils.join([1, 2, 3], null) = "123"
              -800     * </pre>
              -801     *
              -802     * @param array
              -803     *            the array of values to join together, may be null
              -804     * @param separator
              -805     *            the separator character to use
              -806     * @param startIndex
              -807     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              -808     *            array
              -809     * @param endIndex
              -810     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              -811     *            the array
              -812     * @return the joined String, {@code null} if null array input
              -813     * @since 3.2
              -814     */
              -815    public static String join(final char[] array, final char separator, final int startIndex, final int endIndex) {
              -816        if (array == null) {
              -817            return null;
              -818        }
              -819        final int noOfItems = endIndex - startIndex;
              -820        if (noOfItems <= 0) {
              -821            return EMPTY;
              -822        }
              -823        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              -824        for (int i = startIndex; i < endIndex; i++) {
              -825            if (i > startIndex) {
              -826                buf.append(separator);
              -827            }
              -828            buf.append(array[i]);
              -829        }
              -830        return buf.toString();
              -831    }
              -832
              -833    /**
              -834     * <p>
              -835     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -836     * </p>
              -837     *
              -838     * <p>
              -839     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -840     * by empty strings.
              -841     * </p>
              -842     *
              -843     * <pre>
              -844     * StringUtils.join(null, *)               = null
              -845     * StringUtils.join([], *)                 = ""
              -846     * StringUtils.join([null], *)             = ""
              -847     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -848     * StringUtils.join([1, 2, 3], null) = "123"
              -849     * </pre>
              -850     *
              -851     * @param array
              -852     *            the array of values to join together, may be null
              -853     * @param separator
              -854     *            the separator character to use
              -855     * @param startIndex
              -856     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              -857     *            array
              -858     * @param endIndex
              -859     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              -860     *            the array
              -861     * @return the joined String, {@code null} if null array input
              -862     * @since 3.2
              -863     */
              -864    public static String join(final double[] array, final char separator, final int startIndex, final int endIndex) {
              -865        if (array == null) {
              -866            return null;
              -867        }
              -868        final int noOfItems = endIndex - startIndex;
              -869        if (noOfItems <= 0) {
              -870            return EMPTY;
              -871        }
              -872        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              -873        for (int i = startIndex; i < endIndex; i++) {
              -874            if (i > startIndex) {
              -875                buf.append(separator);
              -876            }
              -877            buf.append(array[i]);
              -878        }
              -879        return buf.toString();
              -880    }
              -881
              -882    /**
              -883     * <p>
              -884     * Joins the elements of the provided array into a single String containing the provided list of elements.
              -885     * </p>
              -886     *
              -887     * <p>
              -888     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              -889     * by empty strings.
              -890     * </p>
              -891     *
              -892     * <pre>
              -893     * StringUtils.join(null, *)               = null
              -894     * StringUtils.join([], *)                 = ""
              -895     * StringUtils.join([null], *)             = ""
              -896     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              -897     * StringUtils.join([1, 2, 3], null) = "123"
              -898     * </pre>
              -899     *
              -900     * @param array
              -901     *            the array of values to join together, may be null
              -902     * @param separator
              -903     *            the separator character to use
              -904     * @param startIndex
              -905     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              -906     *            array
              -907     * @param endIndex
              -908     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              -909     *            the array
              -910     * @return the joined String, {@code null} if null array input
              -911     * @since 3.2
              -912     */
              -913    public static String join(final float[] array, final char separator, final int startIndex, final int endIndex) {
              -914        if (array == null) {
              -915            return null;
              -916        }
              -917        final int noOfItems = endIndex - startIndex;
              -918        if (noOfItems <= 0) {
              -919            return EMPTY;
              -920        }
              -921        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              -922        for (int i = startIndex; i < endIndex; i++) {
              -923            if (i > startIndex) {
              -924                buf.append(separator);
              -925            }
              -926            buf.append(array[i]);
              -927        }
              -928        return buf.toString();
              -929    }
              -930
              -931
              -932    /**
              -933     * <p>Joins the elements of the provided array into a single String
              -934     * containing the provided list of elements.</p>
              -935     *
              -936     * <p>No delimiter is added before or after the list.
              -937     * A {@code null} separator is the same as an empty String ("").
              -938     * Null objects or empty strings within the array are represented by
              -939     * empty strings.</p>
              -940     *
              -941     * <pre>
              -942     * StringUtils.join(null, *)                = null
              -943     * StringUtils.join([], *)                  = ""
              -944     * StringUtils.join([null], *)              = ""
              -945     * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
              -946     * StringUtils.join(["a", "b", "c"], null)  = "abc"
              -947     * StringUtils.join(["a", "b", "c"], "")    = "abc"
              -948     * StringUtils.join([null, "", "a"], ',')   = ",,a"
              -949     * </pre>
              -950     *
              -951     * @param array  the array of values to join together, may be null
              -952     * @param separator  the separator character to use, null treated as ""
              -953     * @return the joined String, {@code null} if null array input
              -954     */
              -955    public static String join(final Object[] array, final String separator) {
              -956        if (array == null) {
              -957            return null;
              -958        }
              -959        return join(array, separator, 0, array.length);
              -960    }
              -961
              -962    /**
              -963     * <p>Joins the elements of the provided array into a single String
              -964     * containing the provided list of elements.</p>
              -965     *
              -966     * <p>No delimiter is added before or after the list.
              -967     * A {@code null} separator is the same as an empty String ("").
              -968     * Null objects or empty strings within the array are represented by
              -969     * empty strings.</p>
              -970     *
              -971     * <pre>
              -972     * StringUtils.join(null, *, *, *)                = null
              -973     * StringUtils.join([], *, *, *)                  = ""
              -974     * StringUtils.join([null], *, *, *)              = ""
              -975     * StringUtils.join(["a", "b", "c"], "--", 0, 3)  = "a--b--c"
              -976     * StringUtils.join(["a", "b", "c"], "--", 1, 3)  = "b--c"
              -977     * StringUtils.join(["a", "b", "c"], "--", 2, 3)  = "c"
              -978     * StringUtils.join(["a", "b", "c"], "--", 2, 2)  = ""
              -979     * StringUtils.join(["a", "b", "c"], null, 0, 3)  = "abc"
              -980     * StringUtils.join(["a", "b", "c"], "", 0, 3)    = "abc"
              -981     * StringUtils.join([null, "", "a"], ',', 0, 3)   = ",,a"
              -982     * </pre>
              -983     *
              -984     * @param array  the array of values to join together, may be null
              -985     * @param separator  the separator character to use, null treated as ""
              -986     * @param startIndex the first index to start joining from.
              -987     * @param endIndex the index to stop joining from (exclusive).
              -988     * @return the joined String, {@code null} if null array input; or the empty string
              -989     * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by
              -990     * {@code endIndex - startIndex}
              -991     * @throws ArrayIndexOutOfBoundsException ife<br>
              -992     * {@code startIndex < 0} or <br>
              -993     * {@code startIndex >= array.length()} or <br>
              -994     * {@code endIndex < 0} or <br>
              -995     * {@code endIndex > array.length()}
              -996     */
              -997    public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) {
              -998        if (array == null) {
              -999            return null;
              -1000        }
              -1001        if (separator == null) {
              -1002            separator = EMPTY;
              -1003        }
              -1004
              -1005        // endIndex - startIndex > 0:   Len = NofStrings *(len(firstString) + len(separator))
              -1006        //           (Assuming that all Strings are roughly equally long)
              -1007        final int noOfItems = endIndex - startIndex;
              -1008        if (noOfItems <= 0) {
              -1009            return EMPTY;
              -1010        }
              -1011
              -1012        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              -1013
              -1014        for (int i = startIndex; i < endIndex; i++) {
              -1015            if (i > startIndex) {
              -1016                buf.append(separator);
              -1017            }
              -1018            if (array[i] != null) {
              -1019                buf.append(array[i]);
              -1020            }
              -1021        }
              -1022        return buf.toString();
              -1023    }
              -1024
              -1025    /**
              -1026     * <p>Joins the elements of the provided {@code Iterator} into
              -1027     * a single String containing the provided elements.</p>
              -1028     *
              -1029     * <p>No delimiter is added before or after the list. Null objects or empty
              -1030     * strings within the iteration are represented by empty strings.</p>
              -1031     *
              -1032     * <p>See the examples here: {@link #join(Object[],char)}. </p>
              -1033     *
              -1034     * @param iterator  the {@code Iterator} of values to join together, may be null
              -1035     * @param separator  the separator character to use
              -1036     * @return the joined String, {@code null} if null iterator input
              -1037     * @since 2.0
              -1038     */
              -1039    public static String join(final Iterator<?> iterator, final char separator) {
              -1040
              -1041        // handle null, zero and one elements before building a buffer
              -1042        if (iterator == null) {
              -1043            return null;
              -1044        }
              -1045        if (!iterator.hasNext()) {
              -1046            return EMPTY;
              -1047        }
              -1048        final Object first = iterator.next();
              -1049        if (!iterator.hasNext()) {
              -1050            final String result = first != null ? first.toString() : "";
              -1051            return result;
              -1052        }
              -1053
              -1054        // two or more elements
              -1055        final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
              -1056        if (first != null) {
              -1057            buf.append(first);
              -1058        }
              -1059
              -1060        while (iterator.hasNext()) {
              -1061            buf.append(separator);
              -1062            final Object obj = iterator.next();
              -1063            if (obj != null) {
              -1064                buf.append(obj);
              -1065            }
              -1066        }
              -1067
              -1068        return buf.toString();
              -1069    }
              -1070
              -1071    /**
              -1072     * <p>Joins the elements of the provided {@code Iterator} into
              -1073     * a single String containing the provided elements.</p>
              -1074     *
              -1075     * <p>No delimiter is added before or after the list.
              -1076     * A {@code null} separator is the same as an empty String ("").</p>
              -1077     *
              -1078     * <p>See the examples here: {@link #join(Object[],String)}. </p>
              -1079     *
              -1080     * @param iterator  the {@code Iterator} of values to join together, may be null
              -1081     * @param separator  the separator character to use, null treated as ""
              -1082     * @return the joined String, {@code null} if null iterator input
              -1083     */
              -1084    public static String join(final Iterator<?> iterator, final String separator) {
              -1085
              -1086        // handle null, zero and one elements before building a buffer
              -1087        if (iterator == null) {
              -1088            return null;
              -1089        }
              -1090        if (!iterator.hasNext()) {
              -1091            return EMPTY;
              -1092        }
              -1093        final Object first = iterator.next();
              -1094        if (!iterator.hasNext()) {
              -1095            final String result = first != null ? first.toString() : "";
              -1096            return result;
              -1097        }
              -1098
              -1099        // two or more elements
              -1100        final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
              -1101        if (first != null) {
              -1102            buf.append(first);
              -1103        }
              -1104
              -1105        while (iterator.hasNext()) {
              -1106            if (separator != null) {
              -1107                buf.append(separator);
              -1108            }
              -1109            final Object obj = iterator.next();
              -1110            if (obj != null) {
              -1111                buf.append(obj);
              -1112            }
              -1113        }
              -1114        return buf.toString();
              -1115    }
              -1116
              -1117    /**
              -1118     * <p>Joins the elements of the provided {@code Iterable} into
              -1119     * a single String containing the provided elements.</p>
              -1120     *
              -1121     * <p>No delimiter is added before or after the list. Null objects or empty
              -1122     * strings within the iteration are represented by empty strings.</p>
              -1123     *
              -1124     * <p>See the examples here: {@link #join(Object[],char)}. </p>
              -1125     *
              -1126     * @param iterable  the {@code Iterable} providing the values to join together, may be null
              -1127     * @param separator  the separator character to use
              -1128     * @return the joined String, {@code null} if null iterator input
              -1129     * @since 2.3
              -1130     */
              -1131    public static String join(final Iterable<?> iterable, final char separator) {
              -1132        if (iterable == null) {
              -1133            return null;
              -1134        }
              -1135        return join(iterable.iterator(), separator);
              -1136    }
              -1137
              -1138    /**
              -1139     * <p>Joins the elements of the provided {@code Iterable} into
              -1140     * a single String containing the provided elements.</p>
              -1141     *
              -1142     * <p>No delimiter is added before or after the list.
              -1143     * A {@code null} separator is the same as an empty String ("").</p>
              -1144     *
              -1145     * <p>See the examples here: {@link #join(Object[],String)}. </p>
              -1146     *
              -1147     * @param iterable  the {@code Iterable} providing the values to join together, may be null
              -1148     * @param separator  the separator character to use, null treated as ""
              -1149     * @return the joined String, {@code null} if null iterator input
              -1150     * @since 2.3
              -1151     */
              -1152    public static String join(final Iterable<?> iterable, final String separator) {
              -1153        if (iterable == null) {
              -1154            return null;
              -1155        }
              -1156        return join(iterable.iterator(), separator);
              -1157    }
              -1158
              -1159
              -1160    /**
              -1161     * <p>Checks if the CharSequence contains only Unicode digits.
              -1162     * A decimal point is not a Unicode digit and returns false.</p>
              -1163     *
              -1164     * <p>{@code null} will return {@code false}.
              -1165     * An empty CharSequence (length()=0) will return {@code false}.</p>
              -1166     *
              -1167     * <p>Note that the method does not allow for a leading sign, either positive or negative.
              -1168     * Also, if a String passes the numeric test, it may still generate a NumberFormatException
              -1169     * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range
              -1170     * for int or long respectively.</p>
              -1171     *
              -1172     * <pre>
              -1173     * StringUtils.isNumeric(null)   = false
              -1174     * StringUtils.isNumeric("")     = false
              -1175     * StringUtils.isNumeric("  ")   = false
              -1176     * StringUtils.isNumeric("123")  = true
              -1177     * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
              -1178     * StringUtils.isNumeric("12 3") = false
              -1179     * StringUtils.isNumeric("ab2c") = false
              -1180     * StringUtils.isNumeric("12-3") = false
              -1181     * StringUtils.isNumeric("12.3") = false
              -1182     * StringUtils.isNumeric("-123") = false
              -1183     * StringUtils.isNumeric("+123") = false
              -1184     * </pre>
              -1185     *
              -1186     * @param cs  the CharSequence to check, may be null
              -1187     * @return {@code true} if only contains digits, and is non-null
              -1188     * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
              -1189     * @since 3.0 Changed "" to return false and not true
              -1190     */
              -1191    public static boolean isNumeric(final CharSequence cs) {
              -1192        if (cs == null || cs.length() == 0) {
              -1193            return false;
              -1194        }
              -1195        final int sz = cs.length();
              -1196        for (int i = 0; i < sz; i++) {
              -1197            if (!Character.isDigit(cs.charAt(i))) {
              -1198                return false;
              -1199            }
              -1200        }
              -1201        return true;
              -1202    }
              -1203
              -1204
              -1205    // startsWith
              -1206    //-----------------------------------------------------------------------
              -1207
              -1208    /**
              -1209     * <p>Check if a CharSequence starts with a specified prefix.</p>
              -1210     *
              -1211     * <p>{@code null}s are handled without exceptions. Two {@code null}
              -1212     * references are considered to be equal. The comparison is case sensitive.</p>
              -1213     *
              -1214     * <pre>
              -1215     * StringUtils.startsWith(null, null)      = true
              -1216     * StringUtils.startsWith(null, "abc")     = false
              -1217     * StringUtils.startsWith("abcdef", null)  = false
              -1218     * StringUtils.startsWith("abcdef", "abc") = true
              -1219     * StringUtils.startsWith("ABCDEF", "abc") = false
              -1220     * </pre>
              -1221     *
              -1222     * @see java.lang.String#startsWith(String)
              -1223     * @param str  the CharSequence to check, may be null
              -1224     * @param prefix the prefix to find, may be null
              -1225     * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or
              -1226     *  both {@code null}
              -1227     * @since 2.4
              -1228     * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
              -1229     */
              -1230    public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
              -1231        return startsWith(str, prefix, false);
              -1232    }
              -1233
              -1234    /**
              -1235     * <p>Case insensitive check if a CharSequence starts with a specified prefix.</p>
              -1236     *
              -1237     * <p>{@code null}s are handled without exceptions. Two {@code null}
              -1238     * references are considered to be equal. The comparison is case insensitive.</p>
              -1239     *
              -1240     * <pre>
              -1241     * StringUtils.startsWithIgnoreCase(null, null)      = true
              -1242     * StringUtils.startsWithIgnoreCase(null, "abc")     = false
              -1243     * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
              -1244     * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
              -1245     * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
              -1246     * </pre>
              -1247     *
              -1248     * @see java.lang.String#startsWith(String)
              -1249     * @param str  the CharSequence to check, may be null
              -1250     * @param prefix the prefix to find, may be null
              -1251     * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or
              -1252     *  both {@code null}
              -1253     * @since 2.4
              -1254     * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
              -1255     */
              -1256    public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
              -1257        return startsWith(str, prefix, true);
              -1258    }
              -1259
              -1260    /**
              -1261     * <p>Check if a CharSequence starts with a specified prefix (optionally case insensitive).</p>
              -1262     *
              -1263     * @see java.lang.String#startsWith(String)
              -1264     * @param str  the CharSequence to check, may be null
              -1265     * @param prefix the prefix to find, may be null
              -1266     * @param ignoreCase indicates whether the compare should ignore case
              -1267     *  (case insensitive) or not.
              -1268     * @return {@code true} if the CharSequence starts with the prefix or
              -1269     *  both {@code null}
              -1270     */
              -1271    private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
              -1272        if (str == null || prefix == null) {
              -1273            return str == null && prefix == null;
              -1274        }
              -1275        if (prefix.length() > str.length()) {
              -1276            return false;
              -1277        }
              -1278        return regionMatches(str, ignoreCase, 0, prefix, 0, prefix.length());
              -1279    }
              -1280
              -1281    /**
              -1282     * Green implementation of regionMatches.
              -1283     *
              -1284     * @param cs the {@code CharSequence} to be processed
              -1285     * @param ignoreCase whether or not to be case insensitive
              -1286     * @param thisStart the index to start on the {@code cs} CharSequence
              -1287     * @param substring the {@code CharSequence} to be looked for
              -1288     * @param start the index to start on the {@code substring} CharSequence
              -1289     * @param length character length of the region
              -1290     * @return whether the region matched
              -1291     */
              -1292    static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,
              -1293                                 final CharSequence substring, final int start, final int length)    {
              -1294        if (cs instanceof String && substring instanceof String) {
              -1295            return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);
              -1296        }
              -1297        int index1 = thisStart;
              -1298        int index2 = start;
              -1299        int tmpLen = length;
              -1300
              -1301        // Extract these first so we detect NPEs the same as the java.lang.String version
              -1302        final int srcLen = cs.length() - thisStart;
              -1303        final int otherLen = substring.length() - start;
              -1304
              -1305        // Check for invalid parameters
              -1306        if (thisStart < 0 || start < 0 || length < 0) {
              -1307            return false;
              -1308        }
              -1309
              -1310        // Check that the regions are long enough
              -1311        if (srcLen < length || otherLen < length) {
              -1312            return false;
              -1313        }
              -1314
              -1315        while (tmpLen-- > 0) {
              -1316            final char c1 = cs.charAt(index1++);
              -1317            final char c2 = substring.charAt(index2++);
              -1318
              -1319            if (c1 == c2) {
              -1320                continue;
              -1321            }
              -1322
              -1323            if (!ignoreCase) {
              -1324                return false;
              -1325            }
              -1326
              -1327            // The same check as in String.regionMatches():
              -1328            if (Character.toUpperCase(c1) != Character.toUpperCase(c2)
              -1329                    && Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
              -1330                return false;
              -1331            }
              -1332        }
              -1333
              -1334        return true;
              -1335    }
              -1336
              -1337    /**
              -1338     * The index value when an element is not found in a list or array: <code>-1</code>.
              -1339     * This value is returned by methods in this class and can also be used in comparisons with values returned by
              -1340     * various method from {@link java.util.List}.
              -1341     */
              -1342    public static final int INDEX_NOT_FOUND = -1;
              -1343
              -1344    // IndexOf search
              -1345    // ----------------------------------------------------------------------
              -1346
              -1347    // Object IndexOf
              -1348    //-----------------------------------------------------------------------
              -1349    /**
              -1350     * <p>Finds the index of the given object in the array.</p>
              -1351     *
              -1352     * <p>This method returns {@link #INDEX_NOT_FOUND} (<code>-1</code>) for a <code>null</code> input array.</p>
              -1353     *
              -1354     * @param array  the array to search through for the object, may be <code>null</code>
              -1355     * @param objectToFind  the object to find, may be <code>null</code>
              -1356     * @return the index of the object within the array,
              -1357     *  {@link #INDEX_NOT_FOUND} (<code>-1</code>) if not found or <code>null</code> array input
              -1358     */
              -1359    public static int indexOf(Object[] array, Object objectToFind) {
              -1360        return indexOf(array, objectToFind, 0);
              -1361    }
              -1362
              -1363    /**
              -1364     * <p>Finds the index of the given object in the array starting at the given index.</p>
              -1365     *
              -1366     * <p>This method returns {@link #INDEX_NOT_FOUND} (<code>-1</code>) for a <code>null</code> input array.</p>
              -1367     *
              -1368     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
              -1369     * length will return {@link #INDEX_NOT_FOUND} (<code>-1</code>).</p>
              -1370     *
              -1371     * @param array  the array to search through for the object, may be <code>null</code>
              -1372     * @param objectToFind  the object to find, may be <code>null</code>
              -1373     * @param startIndex  the index to start searching at
              -1374     * @return the index of the object within the array starting at the index,
              -1375     *  {@link #INDEX_NOT_FOUND} (<code>-1</code>) if not found or <code>null</code> array input
              -1376     */
              -1377    public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
              -1378        if (array == null) {
              -1379            return INDEX_NOT_FOUND;
              -1380        }
              -1381        if (startIndex < 0) {
              -1382            startIndex = 0;
              -1383        }
              -1384        if (objectToFind == null) {
              -1385            for (int i = startIndex; i < array.length; i++) {
              -1386                if (array[i] == null) {
              -1387                    return i;
              -1388                }
              -1389            }
              -1390        } else {
              -1391            for (int i = startIndex; i < array.length; i++) {
              -1392                if (objectToFind.equals(array[i])) {
              -1393                    return i;
              -1394                }
              -1395            }
              -1396        }
              -1397        return INDEX_NOT_FOUND;
              -1398    }
              -1399}
              +
              001/*
              +002* Licensed to the Apache Software Foundation (ASF) under one or more
              +003* contributor license agreements.  See the NOTICE file distributed with
              +004* this work for additional information regarding copyright ownership.
              +005* The ASF licenses this file to You under the Apache License, Version 2.0
              +006* (the "License"); you may not use this file except in compliance with
              +007* the License.  You may obtain a copy of the License at
              +008*
              +009*      http://www.apache.org/licenses/LICENSE-2.0
              +010*
              +011* Unless required by applicable law or agreed to in writing, software
              +012* distributed under the License is distributed on an "AS IS" BASIS,
              +013* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
              +014* See the License for the specific language governing permissions and
              +015* limitations under the License.
              +016*/
              +017
              +018package co.aikar.commands.apachecommonslang;
              +019
              +020import java.lang.reflect.Array;
              +021import java.util.Iterator;
              +022import java.util.Locale;
              +023
              +024/**
              +025 * Select methods copied from Apache Commons to avoid importing entire lib
              +026 * No changes to logic
              +027 */
              +028public class ApacheCommonsLangUtil {
              +029
              +030    /**
              +031     * The empty String {@code ""}.
              +032     * @since 2.0
              +033     */
              +034    public static final String EMPTY = "";
              +035    /**
              +036     * <p>Shallow clones an array returning a typecast result and handling
              +037     * {@code null}.
              +038     *
              +039     * <p>The objects in the array are not cloned, thus there is no special
              +040     * handling for multi-dimensional arrays.
              +041     *
              +042     * <p>This method returns {@code null} for a {@code null} input array.
              +043     *
              +044     * @param <T> the component type of the array
              +045     * @param array  the array to shallow clone, may be {@code null}
              +046     * @return the cloned array, {@code null} if {@code null} input
              +047     */
              +048    public static <T> T[] clone(final T[] array) {
              +049        if (array == null) {
              +050            return null;
              +051        }
              +052        return array.clone();
              +053    }
              +054
              +055    /**
              +056     * <p>Adds all the elements of the given arrays into a new array.
              +057     * <p>The new array contains all of the element of {@code array1} followed
              +058     * by all of the elements {@code array2}. When an array is returned, it is always
              +059     * a new array.
              +060     *
              +061     * <pre>
              +062     * ArrayUtils.addAll(null, null)     = null
              +063     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
              +064     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
              +065     * ArrayUtils.addAll([], [])         = []
              +066     * ArrayUtils.addAll([null], [null]) = [null, null]
              +067     * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
              +068     * </pre>
              +069     *
              +070     * @param <T> the component type of the array
              +071     * @param array1  the first array whose elements are added to the new array, may be {@code null}
              +072     * @param array2  the second array whose elements are added to the new array, may be {@code null}
              +073     * @return The new array, {@code null} if both arrays are {@code null}.
              +074     *      The type of the new array is the type of the first array,
              +075     *      unless the first array is null, in which case the type is the same as the second array.
              +076     * @since 2.1
              +077     * @throws IllegalArgumentException if the array types are incompatible
              +078     */
              +079    public static <T> T[] addAll(final T[] array1, final T... array2) {
              +080        if (array1 == null) {
              +081            return clone(array2);
              +082        } else if (array2 == null) {
              +083            return clone(array1);
              +084        }
              +085        final Class<?> type1 = array1.getClass().getComponentType();
              +086        @SuppressWarnings("unchecked") // OK, because array is of type T
              +087        final T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
              +088        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
              +089        try {
              +090            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
              +091        } catch (final ArrayStoreException ase) {
              +092            // Check if problem was due to incompatible types
              +093            /*
              +094             * We do this here, rather than before the copy because:
              +095             * - it would be a wasted check most of the time
              +096             * - safer, in case check turns out to be too strict
              +097             */
              +098            final Class<?> type2 = array2.getClass().getComponentType();
              +099            if (!type1.isAssignableFrom(type2)) {
              +100                throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
              +101                        + type1.getName(), ase);
              +102            }
              +103            throw ase; // No, so rethrow original
              +104        }
              +105        return joinedArray;
              +106    }
              +107
              +108    //-----------------------------------------------------------------------
              +109    /**
              +110     * <p>Converts all the whitespace separated words in a String into capitalized words,
              +111     * that is each word is made up of a titlecase character and then a series of
              +112     * lowercase characters.  </p>
              +113     *
              +114     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
              +115     * A <code>null</code> input String returns <code>null</code>.
              +116     * Capitalization uses the Unicode title case, normally equivalent to
              +117     * upper case.</p>
              +118     *
              +119     * <pre>
              +120     * WordUtils.capitalizeFully(null)        = null
              +121     * WordUtils.capitalizeFully("")          = ""
              +122     * WordUtils.capitalizeFully("i am FINE") = "I Am Fine"
              +123     * </pre>
              +124     *
              +125     * @param str  the String to capitalize, may be null
              +126     * @return capitalized String, <code>null</code> if null String input
              +127     */
              +128    public static String capitalizeFully(final String str) {
              +129        return capitalizeFully(str, null);
              +130    }
              +131
              +132    /**
              +133     * <p>Converts all the delimiter separated words in a String into capitalized words,
              +134     * that is each word is made up of a titlecase character and then a series of
              +135     * lowercase characters. </p>
              +136     *
              +137     * <p>The delimiters represent a set of characters understood to separate words.
              +138     * The first string character and the first non-delimiter character after a
              +139     * delimiter will be capitalized. </p>
              +140     *
              +141     * <p>A <code>null</code> input String returns <code>null</code>.
              +142     * Capitalization uses the Unicode title case, normally equivalent to
              +143     * upper case.</p>
              +144     *
              +145     * <pre>
              +146     * WordUtils.capitalizeFully(null, *)            = null
              +147     * WordUtils.capitalizeFully("", *)              = ""
              +148     * WordUtils.capitalizeFully(*, null)            = *
              +149     * WordUtils.capitalizeFully(*, new char[0])     = *
              +150     * WordUtils.capitalizeFully("i aM.fine", {'.'}) = "I am.Fine"
              +151     * </pre>
              +152     *
              +153     * @param str  the String to capitalize, may be null
              +154     * @param delimiters  set of characters to determine capitalization, null means whitespace
              +155     * @return capitalized String, <code>null</code> if null String input
              +156     * @since 2.1
              +157     */
              +158    public static String capitalizeFully(String str, final char... delimiters) {
              +159        final int delimLen = delimiters == null ? -1 : delimiters.length;
              +160        if (str == null || str.isEmpty() || delimLen == 0) {
              +161            return str;
              +162        }
              +163        str = str.toLowerCase(Locale.ENGLISH);
              +164        return capitalize(str, delimiters);
              +165    }
              +166
              +167    // Capitalizing
              +168    //-----------------------------------------------------------------------
              +169    /**
              +170     * <p>Capitalizes all the whitespace separated words in a String.
              +171     * Only the first character of each word is changed. To convert the
              +172     * rest of each word to lowercase at the same time,
              +173     * use {@link #capitalizeFully(String)}.</p>
              +174     *
              +175     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
              +176     * A <code>null</code> input String returns <code>null</code>.
              +177     * Capitalization uses the Unicode title case, normally equivalent to
              +178     * upper case.</p>
              +179     *
              +180     * <pre>
              +181     * WordUtils.capitalize(null)        = null
              +182     * WordUtils.capitalize("")          = ""
              +183     * WordUtils.capitalize("i am FINE") = "I Am FINE"
              +184     * </pre>
              +185     *
              +186     * @param str  the String to capitalize, may be null
              +187     * @return capitalized String, <code>null</code> if null String input
              +188     * @see #capitalizeFully(String)
              +189     */
              +190    public static String capitalize(final String str) {
              +191        return capitalize(str, null);
              +192    }
              +193
              +194    /**
              +195     * <p>Capitalizes all the delimiter separated words in a String.
              +196     * Only the first character of each word is changed. To convert the
              +197     * rest of each word to lowercase at the same time,
              +198     * use {@link #capitalizeFully(String, char[])}.</p>
              +199     *
              +200     * <p>The delimiters represent a set of characters understood to separate words.
              +201     * The first string character and the first non-delimiter character after a
              +202     * delimiter will be capitalized. </p>
              +203     *
              +204     * <p>A <code>null</code> input String returns <code>null</code>.
              +205     * Capitalization uses the Unicode title case, normally equivalent to
              +206     * upper case.</p>
              +207     *
              +208     * <pre>
              +209     * WordUtils.capitalize(null, *)            = null
              +210     * WordUtils.capitalize("", *)              = ""
              +211     * WordUtils.capitalize(*, new char[0])     = *
              +212     * WordUtils.capitalize("i am fine", null)  = "I Am Fine"
              +213     * WordUtils.capitalize("i aM.fine", {'.'}) = "I aM.Fine"
              +214     * </pre>
              +215     *
              +216     * @param str  the String to capitalize, may be null
              +217     * @param delimiters  set of characters to determine capitalization, null means whitespace
              +218     * @return capitalized String, <code>null</code> if null String input
              +219     * @see #capitalizeFully(String)
              +220     * @since 2.1
              +221     */
              +222    public static String capitalize(final String str, final char... delimiters) {
              +223        final int delimLen = delimiters == null ? -1 : delimiters.length;
              +224        if (str == null || str.isEmpty() || delimLen == 0) {
              +225            return str;
              +226        }
              +227        final char[] buffer = str.toCharArray();
              +228        boolean capitalizeNext = true;
              +229        for (int i = 0; i < buffer.length; i++) {
              +230            final char ch = buffer[i];
              +231            if (isDelimiter(ch, delimiters)) {
              +232                capitalizeNext = true;
              +233            } else if (capitalizeNext) {
              +234                buffer[i] = Character.toTitleCase(ch);
              +235                capitalizeNext = false;
              +236            }
              +237        }
              +238        return new String(buffer);
              +239    }
              +240    //-----------------------------------------------------------------------
              +241    /**
              +242     * Is the character a delimiter.
              +243     *
              +244     * @param ch  the character to check
              +245     * @param delimiters  the delimiters
              +246     * @return true if it is a delimiter
              +247     */
              +248    public static boolean isDelimiter(final char ch, final char[] delimiters) {
              +249        if (delimiters == null) {
              +250            return Character.isWhitespace(ch);
              +251        }
              +252        for (final char delimiter : delimiters) {
              +253            if (ch == delimiter) {
              +254                return true;
              +255            }
              +256        }
              +257        return false;
              +258    }
              +259
              +260    // Joining
              +261    //-----------------------------------------------------------------------
              +262    /**
              +263     * <p>Joins the elements of the provided array into a single String
              +264     * containing the provided list of elements.</p>
              +265     *
              +266     * <p>No separator is added to the joined String.
              +267     * Null objects or empty strings within the array are represented by
              +268     * empty strings.</p>
              +269     *
              +270     * <pre>
              +271     * StringUtils.join(null)            = null
              +272     * StringUtils.join([])              = ""
              +273     * StringUtils.join([null])          = ""
              +274     * StringUtils.join(["a", "b", "c"]) = "abc"
              +275     * StringUtils.join([null, "", "a"]) = "a"
              +276     * </pre>
              +277     *
              +278     * @param <T> the specific type of values to join together
              +279     * @param elements  the values to join together, may be null
              +280     * @return the joined String, {@code null} if null array input
              +281     * @since 2.0
              +282     * @since 3.0 Changed signature to use varargs
              +283     */
              +284    @SafeVarargs
              +285    public static <T> String join(final T... elements) {
              +286        return join(elements, null);
              +287    }
              +288
              +289    /**
              +290     * <p>Joins the elements of the provided array into a single String
              +291     * containing the provided list of elements.</p>
              +292     *
              +293     * <p>No delimiter is added before or after the list.
              +294     * Null objects or empty strings within the array are represented by
              +295     * empty strings.</p>
              +296     *
              +297     * <pre>
              +298     * StringUtils.join(null, *)               = null
              +299     * StringUtils.join([], *)                 = ""
              +300     * StringUtils.join([null], *)             = ""
              +301     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
              +302     * StringUtils.join(["a", "b", "c"], null) = "abc"
              +303     * StringUtils.join([null, "", "a"], ';')  = ";;a"
              +304     * </pre>
              +305     *
              +306     * @param array  the array of values to join together, may be null
              +307     * @param separator  the separator character to use
              +308     * @return the joined String, {@code null} if null array input
              +309     * @since 2.0
              +310     */
              +311    public static String join(final Object[] array, final char separator) {
              +312        if (array == null) {
              +313            return null;
              +314        }
              +315        return join(array, separator, 0, array.length);
              +316    }
              +317
              +318    /**
              +319     * <p>
              +320     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +321     * </p>
              +322     *
              +323     * <p>
              +324     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +325     * by empty strings.
              +326     * </p>
              +327     *
              +328     * <pre>
              +329     * StringUtils.join(null, *)               = null
              +330     * StringUtils.join([], *)                 = ""
              +331     * StringUtils.join([null], *)             = ""
              +332     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +333     * StringUtils.join([1, 2, 3], null) = "123"
              +334     * </pre>
              +335     *
              +336     * @param array
              +337     *            the array of values to join together, may be null
              +338     * @param separator
              +339     *            the separator character to use
              +340     * @return the joined String, {@code null} if null array input
              +341     * @since 3.2
              +342     */
              +343    public static String join(final long[] array, final char separator) {
              +344        if (array == null) {
              +345            return null;
              +346        }
              +347        return join(array, separator, 0, array.length);
              +348    }
              +349
              +350    /**
              +351     * <p>
              +352     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +353     * </p>
              +354     *
              +355     * <p>
              +356     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +357     * by empty strings.
              +358     * </p>
              +359     *
              +360     * <pre>
              +361     * StringUtils.join(null, *)               = null
              +362     * StringUtils.join([], *)                 = ""
              +363     * StringUtils.join([null], *)             = ""
              +364     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +365     * StringUtils.join([1, 2, 3], null) = "123"
              +366     * </pre>
              +367     *
              +368     * @param array
              +369     *            the array of values to join together, may be null
              +370     * @param separator
              +371     *            the separator character to use
              +372     * @return the joined String, {@code null} if null array input
              +373     * @since 3.2
              +374     */
              +375    public static String join(final int[] array, final char separator) {
              +376        if (array == null) {
              +377            return null;
              +378        }
              +379        return join(array, separator, 0, array.length);
              +380    }
              +381
              +382    /**
              +383     * <p>
              +384     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +385     * </p>
              +386     *
              +387     * <p>
              +388     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +389     * by empty strings.
              +390     * </p>
              +391     *
              +392     * <pre>
              +393     * StringUtils.join(null, *)               = null
              +394     * StringUtils.join([], *)                 = ""
              +395     * StringUtils.join([null], *)             = ""
              +396     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +397     * StringUtils.join([1, 2, 3], null) = "123"
              +398     * </pre>
              +399     *
              +400     * @param array
              +401     *            the array of values to join together, may be null
              +402     * @param separator
              +403     *            the separator character to use
              +404     * @return the joined String, {@code null} if null array input
              +405     * @since 3.2
              +406     */
              +407    public static String join(final short[] array, final char separator) {
              +408        if (array == null) {
              +409            return null;
              +410        }
              +411        return join(array, separator, 0, array.length);
              +412    }
              +413
              +414    /**
              +415     * <p>
              +416     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +417     * </p>
              +418     *
              +419     * <p>
              +420     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +421     * by empty strings.
              +422     * </p>
              +423     *
              +424     * <pre>
              +425     * StringUtils.join(null, *)               = null
              +426     * StringUtils.join([], *)                 = ""
              +427     * StringUtils.join([null], *)             = ""
              +428     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +429     * StringUtils.join([1, 2, 3], null) = "123"
              +430     * </pre>
              +431     *
              +432     * @param array
              +433     *            the array of values to join together, may be null
              +434     * @param separator
              +435     *            the separator character to use
              +436     * @return the joined String, {@code null} if null array input
              +437     * @since 3.2
              +438     */
              +439    public static String join(final byte[] array, final char separator) {
              +440        if (array == null) {
              +441            return null;
              +442        }
              +443        return join(array, separator, 0, array.length);
              +444    }
              +445
              +446    /**
              +447     * <p>
              +448     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +449     * </p>
              +450     *
              +451     * <p>
              +452     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +453     * by empty strings.
              +454     * </p>
              +455     *
              +456     * <pre>
              +457     * StringUtils.join(null, *)               = null
              +458     * StringUtils.join([], *)                 = ""
              +459     * StringUtils.join([null], *)             = ""
              +460     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +461     * StringUtils.join([1, 2, 3], null) = "123"
              +462     * </pre>
              +463     *
              +464     * @param array
              +465     *            the array of values to join together, may be null
              +466     * @param separator
              +467     *            the separator character to use
              +468     * @return the joined String, {@code null} if null array input
              +469     * @since 3.2
              +470     */
              +471    public static String join(final char[] array, final char separator) {
              +472        if (array == null) {
              +473            return null;
              +474        }
              +475        return join(array, separator, 0, array.length);
              +476    }
              +477
              +478    /**
              +479     * <p>
              +480     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +481     * </p>
              +482     *
              +483     * <p>
              +484     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +485     * by empty strings.
              +486     * </p>
              +487     *
              +488     * <pre>
              +489     * StringUtils.join(null, *)               = null
              +490     * StringUtils.join([], *)                 = ""
              +491     * StringUtils.join([null], *)             = ""
              +492     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +493     * StringUtils.join([1, 2, 3], null) = "123"
              +494     * </pre>
              +495     *
              +496     * @param array
              +497     *            the array of values to join together, may be null
              +498     * @param separator
              +499     *            the separator character to use
              +500     * @return the joined String, {@code null} if null array input
              +501     * @since 3.2
              +502     */
              +503    public static String join(final float[] array, final char separator) {
              +504        if (array == null) {
              +505            return null;
              +506        }
              +507        return join(array, separator, 0, array.length);
              +508    }
              +509
              +510    /**
              +511     * <p>
              +512     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +513     * </p>
              +514     *
              +515     * <p>
              +516     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +517     * by empty strings.
              +518     * </p>
              +519     *
              +520     * <pre>
              +521     * StringUtils.join(null, *)               = null
              +522     * StringUtils.join([], *)                 = ""
              +523     * StringUtils.join([null], *)             = ""
              +524     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +525     * StringUtils.join([1, 2, 3], null) = "123"
              +526     * </pre>
              +527     *
              +528     * @param array
              +529     *            the array of values to join together, may be null
              +530     * @param separator
              +531     *            the separator character to use
              +532     * @return the joined String, {@code null} if null array input
              +533     * @since 3.2
              +534     */
              +535    public static String join(final double[] array, final char separator) {
              +536        if (array == null) {
              +537            return null;
              +538        }
              +539        return join(array, separator, 0, array.length);
              +540    }
              +541
              +542
              +543    /**
              +544     * <p>Joins the elements of the provided array into a single String
              +545     * containing the provided list of elements.</p>
              +546     *
              +547     * <p>No delimiter is added before or after the list.
              +548     * Null objects or empty strings within the array are represented by
              +549     * empty strings.</p>
              +550     *
              +551     * <pre>
              +552     * StringUtils.join(null, *)               = null
              +553     * StringUtils.join([], *)                 = ""
              +554     * StringUtils.join([null], *)             = ""
              +555     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
              +556     * StringUtils.join(["a", "b", "c"], null) = "abc"
              +557     * StringUtils.join([null, "", "a"], ';')  = ";;a"
              +558     * </pre>
              +559     *
              +560     * @param array  the array of values to join together, may be null
              +561     * @param separator  the separator character to use
              +562     * @param startIndex the first index to start joining from.  It is
              +563     * an error to pass in an end index past the end of the array
              +564     * @param endIndex the index to stop joining from (exclusive). It is
              +565     * an error to pass in an end index past the end of the array
              +566     * @return the joined String, {@code null} if null array input
              +567     * @since 2.0
              +568     */
              +569    public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) {
              +570        if (array == null) {
              +571            return null;
              +572        }
              +573        final int noOfItems = endIndex - startIndex;
              +574        if (noOfItems <= 0) {
              +575            return EMPTY;
              +576        }
              +577        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              +578        for (int i = startIndex; i < endIndex; i++) {
              +579            if (i > startIndex) {
              +580                buf.append(separator);
              +581            }
              +582            if (array[i] != null) {
              +583                buf.append(array[i]);
              +584            }
              +585        }
              +586        return buf.toString();
              +587    }
              +588
              +589    /**
              +590     * <p>
              +591     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +592     * </p>
              +593     *
              +594     * <p>
              +595     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +596     * by empty strings.
              +597     * </p>
              +598     *
              +599     * <pre>
              +600     * StringUtils.join(null, *)               = null
              +601     * StringUtils.join([], *)                 = ""
              +602     * StringUtils.join([null], *)             = ""
              +603     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +604     * StringUtils.join([1, 2, 3], null) = "123"
              +605     * </pre>
              +606     *
              +607     * @param array
              +608     *            the array of values to join together, may be null
              +609     * @param separator
              +610     *            the separator character to use
              +611     * @param startIndex
              +612     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              +613     *            array
              +614     * @param endIndex
              +615     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              +616     *            the array
              +617     * @return the joined String, {@code null} if null array input
              +618     * @since 3.2
              +619     */
              +620    public static String join(final long[] array, final char separator, final int startIndex, final int endIndex) {
              +621        if (array == null) {
              +622            return null;
              +623        }
              +624        final int noOfItems = endIndex - startIndex;
              +625        if (noOfItems <= 0) {
              +626            return EMPTY;
              +627        }
              +628        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              +629        for (int i = startIndex; i < endIndex; i++) {
              +630            if (i > startIndex) {
              +631                buf.append(separator);
              +632            }
              +633            buf.append(array[i]);
              +634        }
              +635        return buf.toString();
              +636    }
              +637
              +638    /**
              +639     * <p>
              +640     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +641     * </p>
              +642     *
              +643     * <p>
              +644     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +645     * by empty strings.
              +646     * </p>
              +647     *
              +648     * <pre>
              +649     * StringUtils.join(null, *)               = null
              +650     * StringUtils.join([], *)                 = ""
              +651     * StringUtils.join([null], *)             = ""
              +652     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +653     * StringUtils.join([1, 2, 3], null) = "123"
              +654     * </pre>
              +655     *
              +656     * @param array
              +657     *            the array of values to join together, may be null
              +658     * @param separator
              +659     *            the separator character to use
              +660     * @param startIndex
              +661     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              +662     *            array
              +663     * @param endIndex
              +664     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              +665     *            the array
              +666     * @return the joined String, {@code null} if null array input
              +667     * @since 3.2
              +668     */
              +669    public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) {
              +670        if (array == null) {
              +671            return null;
              +672        }
              +673        final int noOfItems = endIndex - startIndex;
              +674        if (noOfItems <= 0) {
              +675            return EMPTY;
              +676        }
              +677        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              +678        for (int i = startIndex; i < endIndex; i++) {
              +679            if (i > startIndex) {
              +680                buf.append(separator);
              +681            }
              +682            buf.append(array[i]);
              +683        }
              +684        return buf.toString();
              +685    }
              +686
              +687    /**
              +688     * <p>
              +689     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +690     * </p>
              +691     *
              +692     * <p>
              +693     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +694     * by empty strings.
              +695     * </p>
              +696     *
              +697     * <pre>
              +698     * StringUtils.join(null, *)               = null
              +699     * StringUtils.join([], *)                 = ""
              +700     * StringUtils.join([null], *)             = ""
              +701     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +702     * StringUtils.join([1, 2, 3], null) = "123"
              +703     * </pre>
              +704     *
              +705     * @param array
              +706     *            the array of values to join together, may be null
              +707     * @param separator
              +708     *            the separator character to use
              +709     * @param startIndex
              +710     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              +711     *            array
              +712     * @param endIndex
              +713     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              +714     *            the array
              +715     * @return the joined String, {@code null} if null array input
              +716     * @since 3.2
              +717     */
              +718    public static String join(final byte[] array, final char separator, final int startIndex, final int endIndex) {
              +719        if (array == null) {
              +720            return null;
              +721        }
              +722        final int noOfItems = endIndex - startIndex;
              +723        if (noOfItems <= 0) {
              +724            return EMPTY;
              +725        }
              +726        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              +727        for (int i = startIndex; i < endIndex; i++) {
              +728            if (i > startIndex) {
              +729                buf.append(separator);
              +730            }
              +731            buf.append(array[i]);
              +732        }
              +733        return buf.toString();
              +734    }
              +735
              +736    /**
              +737     * <p>
              +738     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +739     * </p>
              +740     *
              +741     * <p>
              +742     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +743     * by empty strings.
              +744     * </p>
              +745     *
              +746     * <pre>
              +747     * StringUtils.join(null, *)               = null
              +748     * StringUtils.join([], *)                 = ""
              +749     * StringUtils.join([null], *)             = ""
              +750     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +751     * StringUtils.join([1, 2, 3], null) = "123"
              +752     * </pre>
              +753     *
              +754     * @param array
              +755     *            the array of values to join together, may be null
              +756     * @param separator
              +757     *            the separator character to use
              +758     * @param startIndex
              +759     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              +760     *            array
              +761     * @param endIndex
              +762     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              +763     *            the array
              +764     * @return the joined String, {@code null} if null array input
              +765     * @since 3.2
              +766     */
              +767    public static String join(final short[] array, final char separator, final int startIndex, final int endIndex) {
              +768        if (array == null) {
              +769            return null;
              +770        }
              +771        final int noOfItems = endIndex - startIndex;
              +772        if (noOfItems <= 0) {
              +773            return EMPTY;
              +774        }
              +775        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              +776        for (int i = startIndex; i < endIndex; i++) {
              +777            if (i > startIndex) {
              +778                buf.append(separator);
              +779            }
              +780            buf.append(array[i]);
              +781        }
              +782        return buf.toString();
              +783    }
              +784
              +785    /**
              +786     * <p>
              +787     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +788     * </p>
              +789     *
              +790     * <p>
              +791     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +792     * by empty strings.
              +793     * </p>
              +794     *
              +795     * <pre>
              +796     * StringUtils.join(null, *)               = null
              +797     * StringUtils.join([], *)                 = ""
              +798     * StringUtils.join([null], *)             = ""
              +799     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +800     * StringUtils.join([1, 2, 3], null) = "123"
              +801     * </pre>
              +802     *
              +803     * @param array
              +804     *            the array of values to join together, may be null
              +805     * @param separator
              +806     *            the separator character to use
              +807     * @param startIndex
              +808     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              +809     *            array
              +810     * @param endIndex
              +811     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              +812     *            the array
              +813     * @return the joined String, {@code null} if null array input
              +814     * @since 3.2
              +815     */
              +816    public static String join(final char[] array, final char separator, final int startIndex, final int endIndex) {
              +817        if (array == null) {
              +818            return null;
              +819        }
              +820        final int noOfItems = endIndex - startIndex;
              +821        if (noOfItems <= 0) {
              +822            return EMPTY;
              +823        }
              +824        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              +825        for (int i = startIndex; i < endIndex; i++) {
              +826            if (i > startIndex) {
              +827                buf.append(separator);
              +828            }
              +829            buf.append(array[i]);
              +830        }
              +831        return buf.toString();
              +832    }
              +833
              +834    /**
              +835     * <p>
              +836     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +837     * </p>
              +838     *
              +839     * <p>
              +840     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +841     * by empty strings.
              +842     * </p>
              +843     *
              +844     * <pre>
              +845     * StringUtils.join(null, *)               = null
              +846     * StringUtils.join([], *)                 = ""
              +847     * StringUtils.join([null], *)             = ""
              +848     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +849     * StringUtils.join([1, 2, 3], null) = "123"
              +850     * </pre>
              +851     *
              +852     * @param array
              +853     *            the array of values to join together, may be null
              +854     * @param separator
              +855     *            the separator character to use
              +856     * @param startIndex
              +857     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              +858     *            array
              +859     * @param endIndex
              +860     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              +861     *            the array
              +862     * @return the joined String, {@code null} if null array input
              +863     * @since 3.2
              +864     */
              +865    public static String join(final double[] array, final char separator, final int startIndex, final int endIndex) {
              +866        if (array == null) {
              +867            return null;
              +868        }
              +869        final int noOfItems = endIndex - startIndex;
              +870        if (noOfItems <= 0) {
              +871            return EMPTY;
              +872        }
              +873        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              +874        for (int i = startIndex; i < endIndex; i++) {
              +875            if (i > startIndex) {
              +876                buf.append(separator);
              +877            }
              +878            buf.append(array[i]);
              +879        }
              +880        return buf.toString();
              +881    }
              +882
              +883    /**
              +884     * <p>
              +885     * Joins the elements of the provided array into a single String containing the provided list of elements.
              +886     * </p>
              +887     *
              +888     * <p>
              +889     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
              +890     * by empty strings.
              +891     * </p>
              +892     *
              +893     * <pre>
              +894     * StringUtils.join(null, *)               = null
              +895     * StringUtils.join([], *)                 = ""
              +896     * StringUtils.join([null], *)             = ""
              +897     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
              +898     * StringUtils.join([1, 2, 3], null) = "123"
              +899     * </pre>
              +900     *
              +901     * @param array
              +902     *            the array of values to join together, may be null
              +903     * @param separator
              +904     *            the separator character to use
              +905     * @param startIndex
              +906     *            the first index to start joining from. It is an error to pass in an end index past the end of the
              +907     *            array
              +908     * @param endIndex
              +909     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
              +910     *            the array
              +911     * @return the joined String, {@code null} if null array input
              +912     * @since 3.2
              +913     */
              +914    public static String join(final float[] array, final char separator, final int startIndex, final int endIndex) {
              +915        if (array == null) {
              +916            return null;
              +917        }
              +918        final int noOfItems = endIndex - startIndex;
              +919        if (noOfItems <= 0) {
              +920            return EMPTY;
              +921        }
              +922        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              +923        for (int i = startIndex; i < endIndex; i++) {
              +924            if (i > startIndex) {
              +925                buf.append(separator);
              +926            }
              +927            buf.append(array[i]);
              +928        }
              +929        return buf.toString();
              +930    }
              +931
              +932
              +933    /**
              +934     * <p>Joins the elements of the provided array into a single String
              +935     * containing the provided list of elements.</p>
              +936     *
              +937     * <p>No delimiter is added before or after the list.
              +938     * A {@code null} separator is the same as an empty String ("").
              +939     * Null objects or empty strings within the array are represented by
              +940     * empty strings.</p>
              +941     *
              +942     * <pre>
              +943     * StringUtils.join(null, *)                = null
              +944     * StringUtils.join([], *)                  = ""
              +945     * StringUtils.join([null], *)              = ""
              +946     * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
              +947     * StringUtils.join(["a", "b", "c"], null)  = "abc"
              +948     * StringUtils.join(["a", "b", "c"], "")    = "abc"
              +949     * StringUtils.join([null, "", "a"], ',')   = ",,a"
              +950     * </pre>
              +951     *
              +952     * @param array  the array of values to join together, may be null
              +953     * @param separator  the separator character to use, null treated as ""
              +954     * @return the joined String, {@code null} if null array input
              +955     */
              +956    public static String join(final Object[] array, final String separator) {
              +957        if (array == null) {
              +958            return null;
              +959        }
              +960        return join(array, separator, 0, array.length);
              +961    }
              +962
              +963    /**
              +964     * <p>Joins the elements of the provided array into a single String
              +965     * containing the provided list of elements.</p>
              +966     *
              +967     * <p>No delimiter is added before or after the list.
              +968     * A {@code null} separator is the same as an empty String ("").
              +969     * Null objects or empty strings within the array are represented by
              +970     * empty strings.</p>
              +971     *
              +972     * <pre>
              +973     * StringUtils.join(null, *, *, *)                = null
              +974     * StringUtils.join([], *, *, *)                  = ""
              +975     * StringUtils.join([null], *, *, *)              = ""
              +976     * StringUtils.join(["a", "b", "c"], "--", 0, 3)  = "a--b--c"
              +977     * StringUtils.join(["a", "b", "c"], "--", 1, 3)  = "b--c"
              +978     * StringUtils.join(["a", "b", "c"], "--", 2, 3)  = "c"
              +979     * StringUtils.join(["a", "b", "c"], "--", 2, 2)  = ""
              +980     * StringUtils.join(["a", "b", "c"], null, 0, 3)  = "abc"
              +981     * StringUtils.join(["a", "b", "c"], "", 0, 3)    = "abc"
              +982     * StringUtils.join([null, "", "a"], ',', 0, 3)   = ",,a"
              +983     * </pre>
              +984     *
              +985     * @param array  the array of values to join together, may be null
              +986     * @param separator  the separator character to use, null treated as ""
              +987     * @param startIndex the first index to start joining from.
              +988     * @param endIndex the index to stop joining from (exclusive).
              +989     * @return the joined String, {@code null} if null array input; or the empty string
              +990     * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by
              +991     * {@code endIndex - startIndex}
              +992     * @throws ArrayIndexOutOfBoundsException ife<br>
              +993     * {@code startIndex < 0} or <br>
              +994     * {@code startIndex >= array.length()} or <br>
              +995     * {@code endIndex < 0} or <br>
              +996     * {@code endIndex > array.length()}
              +997     */
              +998    public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) {
              +999        if (array == null) {
              +1000            return null;
              +1001        }
              +1002        if (separator == null) {
              +1003            separator = EMPTY;
              +1004        }
              +1005
              +1006        // endIndex - startIndex > 0:   Len = NofStrings *(len(firstString) + len(separator))
              +1007        //           (Assuming that all Strings are roughly equally long)
              +1008        final int noOfItems = endIndex - startIndex;
              +1009        if (noOfItems <= 0) {
              +1010            return EMPTY;
              +1011        }
              +1012
              +1013        final StringBuilder buf = new StringBuilder(noOfItems * 16);
              +1014
              +1015        for (int i = startIndex; i < endIndex; i++) {
              +1016            if (i > startIndex) {
              +1017                buf.append(separator);
              +1018            }
              +1019            if (array[i] != null) {
              +1020                buf.append(array[i]);
              +1021            }
              +1022        }
              +1023        return buf.toString();
              +1024    }
              +1025
              +1026    /**
              +1027     * <p>Joins the elements of the provided {@code Iterator} into
              +1028     * a single String containing the provided elements.</p>
              +1029     *
              +1030     * <p>No delimiter is added before or after the list. Null objects or empty
              +1031     * strings within the iteration are represented by empty strings.</p>
              +1032     *
              +1033     * <p>See the examples here: {@link #join(Object[],char)}. </p>
              +1034     *
              +1035     * @param iterator  the {@code Iterator} of values to join together, may be null
              +1036     * @param separator  the separator character to use
              +1037     * @return the joined String, {@code null} if null iterator input
              +1038     * @since 2.0
              +1039     */
              +1040    public static String join(final Iterator<?> iterator, final char separator) {
              +1041
              +1042        // handle null, zero and one elements before building a buffer
              +1043        if (iterator == null) {
              +1044            return null;
              +1045        }
              +1046        if (!iterator.hasNext()) {
              +1047            return EMPTY;
              +1048        }
              +1049        final Object first = iterator.next();
              +1050        if (!iterator.hasNext()) {
              +1051            final String result = first != null ? first.toString() : "";
              +1052            return result;
              +1053        }
              +1054
              +1055        // two or more elements
              +1056        final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
              +1057        if (first != null) {
              +1058            buf.append(first);
              +1059        }
              +1060
              +1061        while (iterator.hasNext()) {
              +1062            buf.append(separator);
              +1063            final Object obj = iterator.next();
              +1064            if (obj != null) {
              +1065                buf.append(obj);
              +1066            }
              +1067        }
              +1068
              +1069        return buf.toString();
              +1070    }
              +1071
              +1072    /**
              +1073     * <p>Joins the elements of the provided {@code Iterator} into
              +1074     * a single String containing the provided elements.</p>
              +1075     *
              +1076     * <p>No delimiter is added before or after the list.
              +1077     * A {@code null} separator is the same as an empty String ("").</p>
              +1078     *
              +1079     * <p>See the examples here: {@link #join(Object[],String)}. </p>
              +1080     *
              +1081     * @param iterator  the {@code Iterator} of values to join together, may be null
              +1082     * @param separator  the separator character to use, null treated as ""
              +1083     * @return the joined String, {@code null} if null iterator input
              +1084     */
              +1085    public static String join(final Iterator<?> iterator, final String separator) {
              +1086
              +1087        // handle null, zero and one elements before building a buffer
              +1088        if (iterator == null) {
              +1089            return null;
              +1090        }
              +1091        if (!iterator.hasNext()) {
              +1092            return EMPTY;
              +1093        }
              +1094        final Object first = iterator.next();
              +1095        if (!iterator.hasNext()) {
              +1096            final String result = first != null ? first.toString() : "";
              +1097            return result;
              +1098        }
              +1099
              +1100        // two or more elements
              +1101        final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
              +1102        if (first != null) {
              +1103            buf.append(first);
              +1104        }
              +1105
              +1106        while (iterator.hasNext()) {
              +1107            if (separator != null) {
              +1108                buf.append(separator);
              +1109            }
              +1110            final Object obj = iterator.next();
              +1111            if (obj != null) {
              +1112                buf.append(obj);
              +1113            }
              +1114        }
              +1115        return buf.toString();
              +1116    }
              +1117
              +1118    /**
              +1119     * <p>Joins the elements of the provided {@code Iterable} into
              +1120     * a single String containing the provided elements.</p>
              +1121     *
              +1122     * <p>No delimiter is added before or after the list. Null objects or empty
              +1123     * strings within the iteration are represented by empty strings.</p>
              +1124     *
              +1125     * <p>See the examples here: {@link #join(Object[],char)}. </p>
              +1126     *
              +1127     * @param iterable  the {@code Iterable} providing the values to join together, may be null
              +1128     * @param separator  the separator character to use
              +1129     * @return the joined String, {@code null} if null iterator input
              +1130     * @since 2.3
              +1131     */
              +1132    public static String join(final Iterable<?> iterable, final char separator) {
              +1133        if (iterable == null) {
              +1134            return null;
              +1135        }
              +1136        return join(iterable.iterator(), separator);
              +1137    }
              +1138
              +1139    /**
              +1140     * <p>Joins the elements of the provided {@code Iterable} into
              +1141     * a single String containing the provided elements.</p>
              +1142     *
              +1143     * <p>No delimiter is added before or after the list.
              +1144     * A {@code null} separator is the same as an empty String ("").</p>
              +1145     *
              +1146     * <p>See the examples here: {@link #join(Object[],String)}. </p>
              +1147     *
              +1148     * @param iterable  the {@code Iterable} providing the values to join together, may be null
              +1149     * @param separator  the separator character to use, null treated as ""
              +1150     * @return the joined String, {@code null} if null iterator input
              +1151     * @since 2.3
              +1152     */
              +1153    public static String join(final Iterable<?> iterable, final String separator) {
              +1154        if (iterable == null) {
              +1155            return null;
              +1156        }
              +1157        return join(iterable.iterator(), separator);
              +1158    }
              +1159
              +1160
              +1161    /**
              +1162     * <p>Checks if the CharSequence contains only Unicode digits.
              +1163     * A decimal point is not a Unicode digit and returns false.</p>
              +1164     *
              +1165     * <p>{@code null} will return {@code false}.
              +1166     * An empty CharSequence (length()=0) will return {@code false}.</p>
              +1167     *
              +1168     * <p>Note that the method does not allow for a leading sign, either positive or negative.
              +1169     * Also, if a String passes the numeric test, it may still generate a NumberFormatException
              +1170     * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range
              +1171     * for int or long respectively.</p>
              +1172     *
              +1173     * <pre>
              +1174     * StringUtils.isNumeric(null)   = false
              +1175     * StringUtils.isNumeric("")     = false
              +1176     * StringUtils.isNumeric("  ")   = false
              +1177     * StringUtils.isNumeric("123")  = true
              +1178     * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
              +1179     * StringUtils.isNumeric("12 3") = false
              +1180     * StringUtils.isNumeric("ab2c") = false
              +1181     * StringUtils.isNumeric("12-3") = false
              +1182     * StringUtils.isNumeric("12.3") = false
              +1183     * StringUtils.isNumeric("-123") = false
              +1184     * StringUtils.isNumeric("+123") = false
              +1185     * </pre>
              +1186     *
              +1187     * @param cs  the CharSequence to check, may be null
              +1188     * @return {@code true} if only contains digits, and is non-null
              +1189     * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
              +1190     * @since 3.0 Changed "" to return false and not true
              +1191     */
              +1192    public static boolean isNumeric(final CharSequence cs) {
              +1193        if (cs == null || cs.length() == 0) {
              +1194            return false;
              +1195        }
              +1196        final int sz = cs.length();
              +1197        for (int i = 0; i < sz; i++) {
              +1198            if (!Character.isDigit(cs.charAt(i))) {
              +1199                return false;
              +1200            }
              +1201        }
              +1202        return true;
              +1203    }
              +1204
              +1205
              +1206    // startsWith
              +1207    //-----------------------------------------------------------------------
              +1208
              +1209    /**
              +1210     * <p>Check if a CharSequence starts with a specified prefix.</p>
              +1211     *
              +1212     * <p>{@code null}s are handled without exceptions. Two {@code null}
              +1213     * references are considered to be equal. The comparison is case sensitive.</p>
              +1214     *
              +1215     * <pre>
              +1216     * StringUtils.startsWith(null, null)      = true
              +1217     * StringUtils.startsWith(null, "abc")     = false
              +1218     * StringUtils.startsWith("abcdef", null)  = false
              +1219     * StringUtils.startsWith("abcdef", "abc") = true
              +1220     * StringUtils.startsWith("ABCDEF", "abc") = false
              +1221     * </pre>
              +1222     *
              +1223     * @see java.lang.String#startsWith(String)
              +1224     * @param str  the CharSequence to check, may be null
              +1225     * @param prefix the prefix to find, may be null
              +1226     * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or
              +1227     *  both {@code null}
              +1228     * @since 2.4
              +1229     * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
              +1230     */
              +1231    public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
              +1232        return startsWith(str, prefix, false);
              +1233    }
              +1234
              +1235    /**
              +1236     * <p>Case insensitive check if a CharSequence starts with a specified prefix.</p>
              +1237     *
              +1238     * <p>{@code null}s are handled without exceptions. Two {@code null}
              +1239     * references are considered to be equal. The comparison is case insensitive.</p>
              +1240     *
              +1241     * <pre>
              +1242     * StringUtils.startsWithIgnoreCase(null, null)      = true
              +1243     * StringUtils.startsWithIgnoreCase(null, "abc")     = false
              +1244     * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
              +1245     * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
              +1246     * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
              +1247     * </pre>
              +1248     *
              +1249     * @see java.lang.String#startsWith(String)
              +1250     * @param str  the CharSequence to check, may be null
              +1251     * @param prefix the prefix to find, may be null
              +1252     * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or
              +1253     *  both {@code null}
              +1254     * @since 2.4
              +1255     * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
              +1256     */
              +1257    public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
              +1258        return startsWith(str, prefix, true);
              +1259    }
              +1260
              +1261    /**
              +1262     * <p>Check if a CharSequence starts with a specified prefix (optionally case insensitive).</p>
              +1263     *
              +1264     * @see java.lang.String#startsWith(String)
              +1265     * @param str  the CharSequence to check, may be null
              +1266     * @param prefix the prefix to find, may be null
              +1267     * @param ignoreCase indicates whether the compare should ignore case
              +1268     *  (case insensitive) or not.
              +1269     * @return {@code true} if the CharSequence starts with the prefix or
              +1270     *  both {@code null}
              +1271     */
              +1272    private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
              +1273        if (str == null || prefix == null) {
              +1274            return str == null && prefix == null;
              +1275        }
              +1276        if (prefix.length() > str.length()) {
              +1277            return false;
              +1278        }
              +1279        return regionMatches(str, ignoreCase, 0, prefix, 0, prefix.length());
              +1280    }
              +1281
              +1282    /**
              +1283     * Green implementation of regionMatches.
              +1284     *
              +1285     * @param cs the {@code CharSequence} to be processed
              +1286     * @param ignoreCase whether or not to be case insensitive
              +1287     * @param thisStart the index to start on the {@code cs} CharSequence
              +1288     * @param substring the {@code CharSequence} to be looked for
              +1289     * @param start the index to start on the {@code substring} CharSequence
              +1290     * @param length character length of the region
              +1291     * @return whether the region matched
              +1292     */
              +1293    static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,
              +1294                                 final CharSequence substring, final int start, final int length)    {
              +1295        if (cs instanceof String && substring instanceof String) {
              +1296            return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);
              +1297        }
              +1298        int index1 = thisStart;
              +1299        int index2 = start;
              +1300        int tmpLen = length;
              +1301
              +1302        // Extract these first so we detect NPEs the same as the java.lang.String version
              +1303        final int srcLen = cs.length() - thisStart;
              +1304        final int otherLen = substring.length() - start;
              +1305
              +1306        // Check for invalid parameters
              +1307        if (thisStart < 0 || start < 0 || length < 0) {
              +1308            return false;
              +1309        }
              +1310
              +1311        // Check that the regions are long enough
              +1312        if (srcLen < length || otherLen < length) {
              +1313            return false;
              +1314        }
              +1315
              +1316        while (tmpLen-- > 0) {
              +1317            final char c1 = cs.charAt(index1++);
              +1318            final char c2 = substring.charAt(index2++);
              +1319
              +1320            if (c1 == c2) {
              +1321                continue;
              +1322            }
              +1323
              +1324            if (!ignoreCase) {
              +1325                return false;
              +1326            }
              +1327
              +1328            // The same check as in String.regionMatches():
              +1329            if (Character.toUpperCase(c1) != Character.toUpperCase(c2)
              +1330                    && Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
              +1331                return false;
              +1332            }
              +1333        }
              +1334
              +1335        return true;
              +1336    }
              +1337
              +1338    /**
              +1339     * The index value when an element is not found in a list or array: <code>-1</code>.
              +1340     * This value is returned by methods in this class and can also be used in comparisons with values returned by
              +1341     * various method from {@link java.util.List}.
              +1342     */
              +1343    public static final int INDEX_NOT_FOUND = -1;
              +1344
              +1345    // IndexOf search
              +1346    // ----------------------------------------------------------------------
              +1347
              +1348    // Object IndexOf
              +1349    //-----------------------------------------------------------------------
              +1350    /**
              +1351     * <p>Finds the index of the given object in the array.</p>
              +1352     *
              +1353     * <p>This method returns {@link #INDEX_NOT_FOUND} (<code>-1</code>) for a <code>null</code> input array.</p>
              +1354     *
              +1355     * @param array  the array to search through for the object, may be <code>null</code>
              +1356     * @param objectToFind  the object to find, may be <code>null</code>
              +1357     * @return the index of the object within the array,
              +1358     *  {@link #INDEX_NOT_FOUND} (<code>-1</code>) if not found or <code>null</code> array input
              +1359     */
              +1360    public static int indexOf(Object[] array, Object objectToFind) {
              +1361        return indexOf(array, objectToFind, 0);
              +1362    }
              +1363
              +1364    /**
              +1365     * <p>Finds the index of the given object in the array starting at the given index.</p>
              +1366     *
              +1367     * <p>This method returns {@link #INDEX_NOT_FOUND} (<code>-1</code>) for a <code>null</code> input array.</p>
              +1368     *
              +1369     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
              +1370     * length will return {@link #INDEX_NOT_FOUND} (<code>-1</code>).</p>
              +1371     *
              +1372     * @param array  the array to search through for the object, may be <code>null</code>
              +1373     * @param objectToFind  the object to find, may be <code>null</code>
              +1374     * @param startIndex  the index to start searching at
              +1375     * @return the index of the object within the array starting at the index,
              +1376     *  {@link #INDEX_NOT_FOUND} (<code>-1</code>) if not found or <code>null</code> array input
              +1377     */
              +1378    public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
              +1379        if (array == null) {
              +1380            return INDEX_NOT_FOUND;
              +1381        }
              +1382        if (startIndex < 0) {
              +1383            startIndex = 0;
              +1384        }
              +1385        if (objectToFind == null) {
              +1386            for (int i = startIndex; i < array.length; i++) {
              +1387                if (array[i] == null) {
              +1388                    return i;
              +1389                }
              +1390            }
              +1391        } else {
              +1392            for (int i = startIndex; i < array.length; i++) {
              +1393                if (objectToFind.equals(array[i])) {
              +1394                    return i;
              +1395                }
              +1396            }
              +1397        }
              +1398        return INDEX_NOT_FOUND;
              +1399    }
              +1400}
               
               
               
              @@ -1467,5 +1469,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/contexts/ContextResolver.html b/docs/acf-core/src-html/co/aikar/commands/contexts/ContextResolver.html index 9406fb91..533eec34 100644 --- a/docs/acf-core/src-html/co/aikar/commands/contexts/ContextResolver.html +++ b/docs/acf-core/src-html/co/aikar/commands/contexts/ContextResolver.html @@ -1,63 +1,64 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.contexts;
              -025
              -026import co.aikar.commands.CommandExecutionContext;
              -027import co.aikar.commands.CommandIssuer;
              -028import co.aikar.commands.InvalidCommandArgument;
              -029
              -030/**
              -031 * This defines a context resolver, which parses {@link T} from {@link C}.
              -032 *
              -033 * @param <T>
              -034 *         The type to be parsed.
              -035 * @param <C>
              -036 *         The type of the context which the resolver would get its data from.
              -037 */
              -038@FunctionalInterface
              -039public interface ContextResolver <T, C extends CommandExecutionContext<?, ? extends CommandIssuer>> {
              -040    /**
              -041     * Parses the context of type {@link C} into {@link T}, or throws an exception.
              -042     *
              -043     * @param c
              -044     *         The context to parse from.
              -045     *
              -046     * @return The parsed instance of the wanted type.
              -047     *
              -048     * @throws InvalidCommandArgument
              -049     *         In case the context contains any discrepancies, it will throw this exception.
              -050     */
              -051    T getContext(C c) throws InvalidCommandArgument;
              -052}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.contexts;
              +025
              +026import co.aikar.commands.CommandExecutionContext;
              +027import co.aikar.commands.CommandIssuer;
              +028import co.aikar.commands.InvalidCommandArgument;
              +029
              +030/**
              +031 * This defines a context resolver, which parses {@link T} from {@link C}.
              +032 *
              +033 * @param <T>
              +034 *         The type to be parsed.
              +035 * @param <C>
              +036 *         The type of the context which the resolver would get its data from.
              +037 */
              +038@FunctionalInterface
              +039public interface ContextResolver <T, C extends CommandExecutionContext<?, ? extends CommandIssuer>> {
              +040    /**
              +041     * Parses the context of type {@link C} into {@link T}, or throws an exception.
              +042     *
              +043     * @param c
              +044     *         The context to parse from.
              +045     *
              +046     * @return The parsed instance of the wanted type.
              +047     *
              +048     * @throws InvalidCommandArgument
              +049     *         In case the context contains any discrepancies, it will throw this exception.
              +050     */
              +051    T getContext(C c) throws InvalidCommandArgument;
              +052}
               
               
               
              @@ -120,5 +121,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/contexts/IssuerAwareContextResolver.html b/docs/acf-core/src-html/co/aikar/commands/contexts/IssuerAwareContextResolver.html index 2fa6fcce..dde04238 100644 --- a/docs/acf-core/src-html/co/aikar/commands/contexts/IssuerAwareContextResolver.html +++ b/docs/acf-core/src-html/co/aikar/commands/contexts/IssuerAwareContextResolver.html @@ -1,41 +1,42 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.contexts;
              -025
              -026import co.aikar.commands.CommandExecutionContext;
              -027import co.aikar.commands.CommandIssuer;
              -028
              -029
              -030public interface IssuerAwareContextResolver<T, C extends CommandExecutionContext<?, ? extends CommandIssuer>> extends ContextResolver<T, C> {}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.contexts;
              +025
              +026import co.aikar.commands.CommandExecutionContext;
              +027import co.aikar.commands.CommandIssuer;
              +028
              +029
              +030public interface IssuerAwareContextResolver<T, C extends CommandExecutionContext<?, ? extends CommandIssuer>> extends ContextResolver<T, C> {}
               
               
               
              @@ -98,5 +99,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/contexts/IssuerOnlyContextResolver.html b/docs/acf-core/src-html/co/aikar/commands/contexts/IssuerOnlyContextResolver.html index eef957c6..81c32ad2 100644 --- a/docs/acf-core/src-html/co/aikar/commands/contexts/IssuerOnlyContextResolver.html +++ b/docs/acf-core/src-html/co/aikar/commands/contexts/IssuerOnlyContextResolver.html @@ -1,45 +1,46 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.contexts;
              -025
              -026import co.aikar.commands.CommandExecutionContext;
              -027import co.aikar.commands.CommandIssuer;
              -028
              -029/**
              -030 * A context resolver that will never consume input, and only resolves using the context of the issuer of the command
              -031 * @param <T>
              -032 * @param <C>
              -033 */
              -034public interface IssuerOnlyContextResolver<T, C extends CommandExecutionContext<?, ? extends CommandIssuer>> extends ContextResolver <T, C> {}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.contexts;
              +025
              +026import co.aikar.commands.CommandExecutionContext;
              +027import co.aikar.commands.CommandIssuer;
              +028
              +029/**
              +030 * A context resolver that will never consume input, and only resolves using the context of the issuer of the command
              +031 * @param <T>
              +032 * @param <C>
              +033 */
              +034public interface IssuerOnlyContextResolver<T, C extends CommandExecutionContext<?, ? extends CommandIssuer>> extends ContextResolver <T, C> {}
               
               
               
              @@ -102,5 +103,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/contexts/OptionalContextResolver.html b/docs/acf-core/src-html/co/aikar/commands/contexts/OptionalContextResolver.html index d8f52465..a486a73a 100644 --- a/docs/acf-core/src-html/co/aikar/commands/contexts/OptionalContextResolver.html +++ b/docs/acf-core/src-html/co/aikar/commands/contexts/OptionalContextResolver.html @@ -1,48 +1,49 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.contexts;
              -025
              -026import co.aikar.commands.CommandExecutionContext;
              -027import co.aikar.commands.CommandIssuer;
              -028
              -029/**
              -030 * The same as {@link ContextResolver}, however it can accept a null context.
              -031 *
              -032 * If the parameter was marked optional, will still be called with an empty args list
              -033 *
              -034 * @param <T>
              -035 * @param <C>
              -036 */
              -037public interface OptionalContextResolver <T, C extends CommandExecutionContext<?, ? extends CommandIssuer>> extends ContextResolver <T, C> {}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.contexts;
              +025
              +026import co.aikar.commands.CommandExecutionContext;
              +027import co.aikar.commands.CommandIssuer;
              +028
              +029/**
              +030 * The same as {@link ContextResolver}, however it can accept a null context.
              +031 *
              +032 * If the parameter was marked optional, will still be called with an empty args list
              +033 *
              +034 * @param <T>
              +035 * @param <C>
              +036 */
              +037public interface OptionalContextResolver <T, C extends CommandExecutionContext<?, ? extends CommandIssuer>> extends ContextResolver <T, C> {}
               
               
               
              @@ -105,5 +106,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/contexts/SenderAwareContextResolver.html b/docs/acf-core/src-html/co/aikar/commands/contexts/SenderAwareContextResolver.html index 5ca47379..46558e45 100644 --- a/docs/acf-core/src-html/co/aikar/commands/contexts/SenderAwareContextResolver.html +++ b/docs/acf-core/src-html/co/aikar/commands/contexts/SenderAwareContextResolver.html @@ -1,47 +1,48 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.contexts;
              -025
              -026import co.aikar.commands.CommandExecutionContext;
              -027import co.aikar.commands.CommandIssuer;
              -028
              -029/**
              -030 * Wrapper for IssuerAwareContextResolver
              -031 *
              -032 * @deprecated Please use {@link IssuerAwareContextResolver}
              -033 * @see IssuerAwareContextResolver
              -034 */
              -035@Deprecated
              -036public interface SenderAwareContextResolver<T, C extends CommandExecutionContext<?, ? extends CommandIssuer>> extends IssuerAwareContextResolver <T, C> {}
              +
              001/*
              +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.contexts;
              +025
              +026import co.aikar.commands.CommandExecutionContext;
              +027import co.aikar.commands.CommandIssuer;
              +028
              +029/**
              +030 * Wrapper for IssuerAwareContextResolver
              +031 *
              +032 * @deprecated Please use {@link IssuerAwareContextResolver}
              +033 * @see IssuerAwareContextResolver
              +034 */
              +035@Deprecated
              +036public interface SenderAwareContextResolver<T, C extends CommandExecutionContext<?, ? extends CommandIssuer>> extends IssuerAwareContextResolver <T, C> {}
               
               
               
              @@ -104,5 +105,6 @@
               
               
              +
              diff --git a/docs/acf-core/src-html/co/aikar/commands/processors/ConditionsProcessor.html b/docs/acf-core/src-html/co/aikar/commands/processors/ConditionsProcessor.html index 3b2d4c95..62c82fd1 100644 --- a/docs/acf-core/src-html/co/aikar/commands/processors/ConditionsProcessor.html +++ b/docs/acf-core/src-html/co/aikar/commands/processors/ConditionsProcessor.html @@ -1,54 +1,55 @@ - + Source code +
              -
              001/*
              -002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              -003 *
              -004 *  Permission is hereby granted, free of charge, to any person obtaining
              -005 *  a copy of this software and associated documentation files (the
              -006 *  "Software"), to deal in the Software without restriction, including
              -007 *  without limitation the rights to use, copy, modify, merge, publish,
              -008 *  distribute, sublicense, and/or sell copies of the Software, and to
              -009 *  permit persons to whom the Software is furnished to do so, subject to
              -010 *  the following conditions:
              -011 *
              -012 *  The above copyright notice and this permission notice shall be
              -013 *  included in all copies or substantial portions of the Software.
              -014 *
              -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              -022 */
              -023
              -024package co.aikar.commands.processors;
              -025
              -026import co.aikar.commands.AnnotationProcessor;
              -027import co.aikar.commands.CommandExecutionContext;
              -028import co.aikar.commands.CommandOperationContext;
              -029import co.aikar.commands.annotation.Conditions;
              -030
              -031@Deprecated /* @deprecated UNFINISHED */
              -032public class ConditionsProcessor implements AnnotationProcessor<Conditions> {
              -033
              -034    @Override
              -035    public void onPreComand(CommandOperationContext context) {
              -036
              -037    }
              -038
              -039    @Override
              -040    public void onPostContextResolution(CommandExecutionContext context, Object resolvedValue) {
              -041
              -042    }
              -043}
              +
              001/*
              +002 * Copyright (c) 2016-2018 Daniel Ennis (Aikar) - MIT License
              +003 *
              +004 *  Permission is hereby granted, free of charge, to any person obtaining
              +005 *  a copy of this software and associated documentation files (the
              +006 *  "Software"), to deal in the Software without restriction, including
              +007 *  without limitation the rights to use, copy, modify, merge, publish,
              +008 *  distribute, sublicense, and/or sell copies of the Software, and to
              +009 *  permit persons to whom the Software is furnished to do so, subject to
              +010 *  the following conditions:
              +011 *
              +012 *  The above copyright notice and this permission notice shall be
              +013 *  included in all copies or substantial portions of the Software.
              +014 *
              +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +022 */
              +023
              +024package co.aikar.commands.processors;
              +025
              +026import co.aikar.commands.AnnotationProcessor;
              +027import co.aikar.commands.CommandExecutionContext;
              +028import co.aikar.commands.CommandOperationContext;
              +029import co.aikar.commands.annotation.Conditions;
              +030
              +031@Deprecated /* @deprecated UNFINISHED */
              +032public class ConditionsProcessor implements AnnotationProcessor<Conditions> {
              +033
              +034    @Override
              +035    public void onPreComand(CommandOperationContext context) {
              +036
              +037    }
              +038
              +039    @Override
              +040    public void onPostContextResolution(CommandExecutionContext context, Object resolvedValue) {
              +041
              +042    }
              +043}
               
               
               
              @@ -111,5 +112,6 @@
               
               
              +
              diff --git a/docs/acf-core/stylesheet.css b/docs/acf-core/stylesheet.css index 98055b22..fa246765 100644 --- a/docs/acf-core/stylesheet.css +++ b/docs/acf-core/stylesheet.css @@ -1,35 +1,51 @@ -/* Javadoc style sheet */ -/* -Overall document style -*/ +/* + * Javadoc style sheet + */ @import url('resources/fonts/dejavu.css'); +/* + * Styles for individual HTML elements. + * + * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular + * HTML element throughout the page. + */ + body { background-color:#ffffff; color:#353833; font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; font-size:14px; margin:0; + padding:0; + height:100%; + width:100%; +} +iframe { + margin:0; + padding:0; + height:100%; + width:100%; + overflow-y:scroll; + border:none; } a:link, a:visited { text-decoration:none; color:#4A6782; } -a:hover, a:focus { +a[href]:hover, a[href]:focus { text-decoration:none; color:#bb7a2a; } -a:active { - text-decoration:none; - color:#4A6782; -} a[name] { color:#353833; } -a[name]:hover { - text-decoration:none; - color:#353833; +a[name]:before, a[name]:target, a[id]:before, a[id]:target { + content:""; + display:inline-block; + position:relative; + padding-top:129px; + margin-top:-129px; } pre { font-family:'DejaVu Sans Mono', monospace; @@ -78,9 +94,16 @@ table tr td dt code { sup { font-size:8px; } + /* -Document title and Copyright styles -*/ + * Styles for HTML generated by javadoc. + * + * These are style classes that are used by the standard doclet to generate HTML documentation. + */ + +/* + * Styles for document title and copyright. + */ .clear { clear:both; height:0px; @@ -111,8 +134,8 @@ Document title and Copyright styles font-weight:bold; } /* -Navigation bar styles -*/ + * Styles for navigation bar. + */ .bar { background-color:#4D7A97; color:#FFFFFF; @@ -121,6 +144,15 @@ Navigation bar styles font-size:11px; margin:0; } +.navPadding { + padding-top: 107px; +} +.fixedNav { + position:fixed; + width:100%; + z-index:999; + background-color:#ffffff; +} .topNav { background-color:#4D7A97; color:#FFFFFF; @@ -170,7 +202,22 @@ ul.navList li{ padding: 5px 6px; text-transform:uppercase; } -ul.subNavList li{ +ul.navListSearch { + float:right; + margin:0 0 0 0; + padding:0; +} +ul.navListSearch li { + list-style:none; + float:right; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch li label { + position:relative; + right:-16px; +} +ul.subNavList li { list-style:none; float:left; } @@ -196,21 +243,29 @@ ul.subNavList li{ overflow:hidden; } /* -Page header and footer styles -*/ + * Styles for page header and footer. + */ .header, .footer { clear:both; margin:0 20px; padding:5px 0 0 0; } -.indexHeader { - margin:10px; +.indexNav { position:relative; + font-size:12px; + background-color:#dee3e9; } -.indexHeader span{ - margin-right:15px; +.indexNav ul { + margin-top:0; + padding:5px; } -.indexHeader h1 { +.indexNav ul li { + display:inline; + list-style-type:none; + padding-right:10px; + text-transform:uppercase; +} +.indexNav h1 { font-size:13px; } .title { @@ -232,8 +287,8 @@ Page header and footer styles font-size:13px; } /* -Heading styles -*/ + * Styles for headings. + */ div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { background-color:#dee3e9; border:1px solid #d0d9e0; @@ -254,9 +309,10 @@ ul.blockList li.blockList h2 { padding:0px 0 20px 0; } /* -Page layout container styles -*/ -.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + * Styles for page layout containers. + */ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer, +.allClassesContainer, .allPackagesContainer { clear:both; padding:10px 20px; position:relative; @@ -287,7 +343,7 @@ Page layout container styles .contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { margin:5px 0 10px 0px; font-size:14px; - font-family:'DejaVu Sans Mono',monospace; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } .serializedFormContainer dl.nameValue dt { margin-left:1px; @@ -301,8 +357,11 @@ Page layout container styles display:inline; } /* -List styles -*/ + * Styles for lists. + */ +li.circle { + list-style:circle; +} ul.horizontal li { display:inline; font-size:0.9em; @@ -355,19 +414,22 @@ table tr td dl, table tr td dl dt, table tr td dl dd { margin-bottom:1px; } /* -Table styles -*/ -.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + * Styles for tables. + */ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary, +.requiresSummary, .packagesSummary, .providesSummary, .usesSummary { width:100%; + border-spacing:0; border-left:1px solid #EEE; border-right:1px solid #EEE; border-bottom:1px solid #EEE; } -.overviewSummary, .memberSummary { +.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary { padding:0px; } .overviewSummary caption, .memberSummary caption, .typeSummary caption, -.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption, +.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption { position:relative; text-align:left; background-repeat:no-repeat; @@ -382,17 +444,31 @@ Table styles white-space:pre; } .overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, -.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.constantsSummary caption a:link, .deprecatedSummary caption a:link, +.requiresSummary caption a:link, .packagesSummary caption a:link, .providesSummary caption a:link, +.usesSummary caption a:link, .overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, -.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.requiresSummary caption a:hover, .packagesSummary caption a:hover, .providesSummary caption a:hover, +.usesSummary caption a:hover, .overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, -.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.constantsSummary caption a:active, .deprecatedSummary caption a:active, +.requiresSummary caption a:active, .packagesSummary caption a:active, .providesSummary caption a:active, +.usesSummary caption a:active, .overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, -.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { +.constantsSummary caption a:visited, .deprecatedSummary caption a:visited, +.requiresSummary caption a:visited, .packagesSummary caption a:visited, .providesSummary caption a:visited, +.usesSummary caption a:visited { color:#FFFFFF; } +.useSummary caption a:link, .useSummary caption a:hover, .useSummary caption a:active, +.useSummary caption a:visited { + color:#1f389c; +} .overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, -.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span, +.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span, +.usesSummary caption span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -404,7 +480,8 @@ Table styles border: none; height:16px; } -.memberSummary caption span.activeTableTab span { +.memberSummary caption span.activeTableTab span, .packagesSummary caption span.activeTableTab span, +.overviewSummary caption span.activeTableTab span, .typeSummary caption span.activeTableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -415,7 +492,8 @@ Table styles background-color:#F8981D; height:16px; } -.memberSummary caption span.tableTab span { +.memberSummary caption span.tableTab span, .packagesSummary caption span.tableTab span, +.overviewSummary caption span.tableTab span, .typeSummary caption span.tableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -426,7 +504,10 @@ Table styles background-color:#4D7A97; height:16px; } -.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab, +.packagesSummary caption span.tableTab, .packagesSummary caption span.activeTableTab, +.overviewSummary caption span.tableTab, .overviewSummary caption span.activeTableTab, +.typeSummary caption span.tableTab, .typeSummary caption span.activeTableTab { padding-top:0px; padding-left:0px; padding-right:0px; @@ -435,14 +516,16 @@ Table styles display:inline; } .overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, -.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd, +.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd { display:none; width:5px; position:relative; float:left; background-color:#F8981D; } -.memberSummary .activeTableTab .tabEnd { +.memberSummary .activeTableTab .tabEnd, .packagesSummary .activeTableTab .tabEnd, +.overviewSummary .activeTableTab .tabEnd, .typeSummary .activeTableTab .tabEnd { display:none; width:5px; margin-right:3px; @@ -450,66 +533,88 @@ Table styles float:left; background-color:#F8981D; } -.memberSummary .tableTab .tabEnd { +.memberSummary .tableTab .tabEnd, .packagesSummary .tableTab .tabEnd, +.overviewSummary .tableTab .tabEnd, .typeSummary .tableTab .tabEnd { display:none; width:5px; margin-right:3px; position:relative; background-color:#4D7A97; float:left; - +} +.rowColor th, .altColor th { + font-weight:normal; } .overviewSummary td, .memberSummary td, .typeSummary td, -.useSummary td, .constantsSummary td, .deprecatedSummary td { +.useSummary td, .constantsSummary td, .deprecatedSummary td, +.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td { text-align:left; padding:0px 0px 12px 10px; } -th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, -td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .useSummary th, +.constantsSummary th, .packagesSummary th, td.colFirst, td.colSecond, td.colLast, .useSummary td, +.constantsSummary td { vertical-align:top; padding-right:0px; padding-top:8px; padding-bottom:3px; } -th.colFirst, th.colLast, th.colOne, .constantsSummary th { +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .constantsSummary th, +.packagesSummary th { background:#dee3e9; text-align:left; padding:8px 3px 3px 7px; } td.colFirst, th.colFirst { - white-space:nowrap; font-size:13px; } -td.colLast, th.colLast { +td.colSecond, th.colSecond, td.colLast, th.colConstructorName, th.colDeprecatedItemName, th.colLast { font-size:13px; } -td.colOne, th.colOne { +.constantsSummary th, .packagesSummary th { + font-size:13px; +} +.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst, +.providesSummary td.colLast { + white-space:normal; font-size:13px; } .overviewSummary td.colFirst, .overviewSummary th.colFirst, -.useSummary td.colFirst, .useSummary th.colFirst, -.overviewSummary td.colOne, .overviewSummary th.colOne, +.requiresSummary td.colFirst, .requiresSummary th.colFirst, +.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th, +.usesSummary td.colFirst, .usesSummary th.colFirst, +.providesSummary td.colFirst, .providesSummary th.colFirst, .memberSummary td.colFirst, .memberSummary th.colFirst, -.memberSummary td.colOne, .memberSummary th.colOne, -.typeSummary td.colFirst{ - width:25%; +.memberSummary td.colSecond, .memberSummary th.colSecond, .memberSummary th.colConstructorName, +.typeSummary td.colFirst, .typeSummary th.colFirst { vertical-align:top; } -td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { +.packagesSummary th.colLast, .packagesSummary td.colLast { + white-space:normal; +} +td.colFirst a:link, td.colFirst a:visited, +td.colSecond a:link, td.colSecond a:visited, +th.colFirst a:link, th.colFirst a:visited, +th.colSecond a:link, th.colSecond a:visited, +th.colConstructorName a:link, th.colConstructorName a:visited, +th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited, +.constantValuesContainer td a:link, .constantValuesContainer td a:visited, +.allClassesContainer td a:link, .allClassesContainer td a:visited, +.allPackagesContainer td a:link, .allPackagesContainer td a:visited { font-weight:bold; } .tableSubHeadingColor { background-color:#EEEEFF; } -.altColor { +.altColor, .altColor th { background-color:#FFFFFF; } -.rowColor { +.rowColor, .rowColor th { background-color:#EEEEEF; } /* -Content styles -*/ + * Styles for contents. + */ .description pre { margin-top:0; } @@ -520,27 +625,22 @@ Content styles .docSummary { padding:0; } - ul.blockList ul.blockList ul.blockList li.blockList h3 { font-style:normal; } - div.block { font-size:14px; font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } - td.colLast div { padding-top:0px; } - - td.colLast a { padding-bottom:3px; } /* -Formatting effect styles -*/ + * Styles for formatting effect. + */ .sourceLineNo { color:green; padding:0 30px 0 0; @@ -555,20 +655,252 @@ h1.hidden { margin:3px 10px 2px 0px; color:#474747; } -.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { +.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink, +.moduleLabelInPackage, .moduleLabelInType, .overrideSpecifyLabel, .packageLabelInType, +.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, +.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { font-weight:bold; } .deprecationComment, .emphasizedPhrase, .interfaceName { font-style:italic; } - -div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +.deprecationBlock { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +div.block div.deprecationComment, div.block div.block span.emphasizedPhrase, div.block div.block span.interfaceName { font-style:normal; } - -div.contentContainer ul.blockList li.blockList h2{ +div.contentContainer ul.blockList li.blockList h2 { padding-bottom:0px; } +/* + * Styles for IFRAME. + */ +.mainContainer { + margin:0 auto; + padding:0; + height:100%; + width:100%; + position:fixed; + top:0; + left:0; +} +.leftContainer { + height:100%; + position:fixed; + width:320px; +} +.leftTop { + position:relative; + float:left; + width:315px; + top:0; + left:0; + height:30%; + border-right:6px solid #ccc; + border-bottom:6px solid #ccc; +} +.leftBottom { + position:relative; + float:left; + width:315px; + bottom:0; + left:0; + height:70%; + border-right:6px solid #ccc; + border-top:1px solid #000; +} +.rightContainer { + position:absolute; + left:320px; + top:0; + bottom:0; + height:100%; + right:0; + border-left:1px solid #000; +} +.rightIframe { + margin:0; + padding:0; + height:100%; + right:30px; + width:100%; + overflow:visible; + margin-bottom:30px; +} +/* + * Styles specific to HTML5 elements. + */ +main, nav, header, footer, section { + display:block; +} +/* + * Styles for javadoc search. + */ +.ui-autocomplete-category { + font-weight:bold; + font-size:15px; + padding:7px 0 7px 3px; + background-color:#4D7A97; + color:#FFFFFF; +} +.resultItem { + font-size:13px; +} +.ui-autocomplete { + max-height:85%; + max-width:65%; + overflow-y:scroll; + overflow-x:scroll; + white-space:nowrap; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); +} +ul.ui-autocomplete { + position:fixed; + z-index:999999; +} +ul.ui-autocomplete li { + float:left; + clear:both; + width:100%; +} +.resultHighlight { + font-weight:bold; +} +#search { + background-image:url('resources/glass.png'); + background-size:13px; + background-repeat:no-repeat; + background-position:2px 3px; + padding-left:20px; + position:relative; + right:-18px; +} +#reset { + background-color: rgb(255,255,255); + background-image:url('resources/x.png'); + background-position:center; + background-repeat:no-repeat; + background-size:12px; + border:0 none; + width:16px; + height:17px; + position:relative; + left:-4px; + top:-4px; + font-size:0px; +} +.watermark { + color:#545454; +} +.searchTagDescResult { + font-style:italic; + font-size:11px; +} +.searchTagHolderResult { + font-style:italic; + font-size:12px; +} +.searchTagResult:before, .searchTagResult:target { + color:red; +} +.moduleGraph span { + display:none; + position:absolute; +} +.moduleGraph:hover span { + display:block; + margin: -100px 0 0 100px; + z-index: 1; +} +.methodSignature { + white-space:normal; +} + +/* + * Styles for user-provided tables. + * + * borderless: + * No borders, vertical margins, styled caption. + * This style is provided for use with existing doc comments. + * In general, borderless tables should not be used for layout purposes. + * + * plain: + * Plain borders around table and cells, vertical margins, styled caption. + * Best for small tables or for complex tables for tables with cells that span + * rows and columns, when the "striped" style does not work well. + * + * striped: + * Borders around the table and vertical borders between cells, striped rows, + * vertical margins, styled caption. + * Best for tables that have a header row, and a body containing a series of simple rows. + */ + +table.borderless, +table.plain, +table.striped { + margin-top: 10px; + margin-bottom: 10px; +} +table.borderless > caption, +table.plain > caption, +table.striped > caption { + font-weight: bold; + font-size: smaller; +} +table.borderless th, table.borderless td, +table.plain th, table.plain td, +table.striped th, table.striped td { + padding: 2px 5px; +} +table.borderless, +table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, +table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { + border: none; +} +table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { + background-color: transparent; +} +table.plain { + border-collapse: collapse; + border: 1px solid black; +} +table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { + background-color: transparent; +} +table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, +table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { + border: 1px solid black; +} +table.striped { + border-collapse: collapse; + border: 1px solid black; +} +table.striped > thead { + background-color: #E3E3E3; +} +table.striped > thead > tr > th, table.striped > thead > tr > td { + border: 1px solid black; +} +table.striped > tbody > tr:nth-child(even) { + background-color: #EEE +} +table.striped > tbody > tr:nth-child(odd) { + background-color: #FFF +} +table.striped > tbody > tr > th, table.striped > tbody > tr > td { + border-left: 1px solid black; + border-right: 1px solid black; +} +table.striped > tbody > tr > th { + font-weight: normal; +} diff --git a/docs/acf-core/type-search-index.js b/docs/acf-core/type-search-index.js new file mode 100644 index 00000000..82fa7ce2 --- /dev/null +++ b/docs/acf-core/type-search-index.js @@ -0,0 +1 @@ +typeSearchIndex = [{"p":"co.aikar.commands","l":"ACFUtil"},{"l":"All Classes","url":"allclasses-index.html"},{"p":"co.aikar.commands","l":"AnnotationProcessor"},{"p":"co.aikar.commands.apachecommonslang","l":"ApacheCommonsExceptionUtil"},{"p":"co.aikar.commands.apachecommonslang","l":"ApacheCommonsLangUtil"},{"p":"co.aikar.commands","l":"CommandCompletions.AsyncCommandCompletionHandler"},{"p":"co.aikar.commands","l":"BaseCommand"},{"p":"co.aikar.commands.annotation","l":"CatchAll"},{"p":"co.aikar.commands.annotation","l":"CatchUnknown"},{"p":"co.aikar.commands.annotation","l":"CommandAlias"},{"p":"co.aikar.commands.annotation","l":"CommandCompletion"},{"p":"co.aikar.commands","l":"CommandCompletionContext"},{"p":"co.aikar.commands","l":"CommandCompletions.CommandCompletionHandler"},{"p":"co.aikar.commands","l":"CommandCompletions"},{"p":"co.aikar.commands","l":"CommandConditions"},{"p":"co.aikar.commands","l":"CommandContexts"},{"p":"co.aikar.commands","l":"CommandExecutionContext"},{"p":"co.aikar.commands","l":"CommandHelp"},{"p":"co.aikar.commands","l":"CommandHelpFormatter"},{"p":"co.aikar.commands","l":"CommandIssuer"},{"p":"co.aikar.commands","l":"CommandManager"},{"p":"co.aikar.commands","l":"CommandOperationContext"},{"p":"co.aikar.commands","l":"CommandParameter"},{"p":"co.aikar.commands.annotation","l":"CommandPermission"},{"p":"co.aikar.commands","l":"CommandReplacements"},{"p":"co.aikar.commands","l":"CommandConditions.Condition"},{"p":"co.aikar.commands","l":"ConditionContext"},{"p":"co.aikar.commands","l":"ConditionFailedException"},{"p":"co.aikar.commands.annotation","l":"Conditions"},{"p":"co.aikar.commands.processors","l":"ConditionsProcessor"},{"p":"co.aikar.commands.contexts","l":"ContextResolver"},{"p":"co.aikar.commands.annotation","l":"Default"},{"p":"co.aikar.commands.annotation","l":"Dependency"},{"p":"co.aikar.commands.annotation","l":"Description"},{"p":"co.aikar.commands","l":"ExceptionHandler"},{"p":"co.aikar.commands.annotation","l":"Flags"},{"p":"co.aikar.commands","l":"ForwardingCommand"},{"p":"co.aikar.commands.annotation","l":"HelpCommand"},{"p":"co.aikar.commands","l":"HelpEntry"},{"p":"co.aikar.commands.annotation","l":"HelpSearchTags"},{"p":"co.aikar.commands","l":"InvalidCommandArgument"},{"p":"co.aikar.commands","l":"InvalidCommandContextException"},{"p":"co.aikar.commands.contexts","l":"IssuerAwareContextResolver"},{"p":"co.aikar.commands","l":"IssuerLocaleChangedCallback"},{"p":"co.aikar.commands.contexts","l":"IssuerOnlyContextResolver"},{"p":"co.aikar.commands","l":"Locales"},{"p":"co.aikar.commands","l":"MessageFormatter"},{"p":"co.aikar.commands","l":"MessageKeys"},{"p":"co.aikar.commands","l":"MessageType"},{"p":"co.aikar.commands.apachecommonslang","l":"ApacheCommonsExceptionUtil.Nestable"},{"p":"co.aikar.commands.annotation","l":"Optional"},{"p":"co.aikar.commands.contexts","l":"OptionalContextResolver"},{"p":"co.aikar.commands","l":"CommandConditions.ParameterCondition"},{"p":"co.aikar.commands.annotation","l":"PreCommand"},{"p":"co.aikar.commands.annotation","l":"Private"},{"p":"co.aikar.commands","l":"RegisteredCommand"},{"p":"co.aikar.commands","l":"RootCommand"},{"p":"co.aikar.commands.contexts","l":"SenderAwareContextResolver"},{"p":"co.aikar.commands","l":"ShowCommandHelp"},{"p":"co.aikar.commands.annotation","l":"Single"},{"p":"co.aikar.commands.annotation","l":"Split"},{"p":"co.aikar.commands.annotation","l":"Subcommand"},{"p":"co.aikar.commands","l":"CommandCompletions.SyncCompletionRequired"},{"p":"co.aikar.commands.annotation","l":"Syntax"},{"p":"co.aikar.commands.annotation","l":"UnknownHandler"},{"p":"co.aikar.commands","l":"UnresolvedDependencyException"},{"p":"co.aikar.commands","l":"UnstableAPI"},{"p":"co.aikar.commands.annotation","l":"Values"}] \ No newline at end of file diff --git a/docs/acf-core/type-search-index.zip b/docs/acf-core/type-search-index.zip new file mode 100644 index 00000000..aeacc19d Binary files /dev/null and b/docs/acf-core/type-search-index.zip differ diff --git a/docs/acf-jda/allclasses-index.html b/docs/acf-jda/allclasses-index.html new file mode 100644 index 00000000..3e459a0a --- /dev/null +++ b/docs/acf-jda/allclasses-index.html @@ -0,0 +1,249 @@ + + + + + +All Classes (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
              + +
              +
              +
              +

              All Classes

              +
              +
              + +
              +
              +
              + +

              Copyright © 2020. All rights reserved.

              +
              + + diff --git a/docs/acf-jda/allclasses.html b/docs/acf-jda/allclasses.html new file mode 100644 index 00000000..ca64cf95 --- /dev/null +++ b/docs/acf-jda/allclasses.html @@ -0,0 +1,46 @@ + + + + + +All Classes (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + +

              All Classes

              +
              + +
              + + diff --git a/docs/acf-jda/allpackages-index.html b/docs/acf-jda/allpackages-index.html new file mode 100644 index 00000000..99c179f3 --- /dev/null +++ b/docs/acf-jda/allpackages-index.html @@ -0,0 +1,169 @@ + + + + + +All Packages (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
              + +
              +
              +
              +

              All Packages

              +
              +
              + +
              +
              +
              + +

              Copyright © 2020. All rights reserved.

              +
              + + diff --git a/docs/acf-jda/co/aikar/commands/CommandConfig.html b/docs/acf-jda/co/aikar/commands/CommandConfig.html index b85543fb..d0665c54 100644 --- a/docs/acf-jda/co/aikar/commands/CommandConfig.html +++ b/docs/acf-jda/co/aikar/commands/CommandConfig.html @@ -1,12 +1,21 @@ - + - CommandConfig (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Interface CommandConfig

              @@ -100,16 +124,15 @@ var activeTableTab = "activeTableTab";
            • All Superinterfaces:
              -
              CommandConfigProvider
              +
              CommandConfigProvider
              All Known Implementing Classes:
              -
              JDACommandConfig
              +
              JDACommandConfig

              -
              public interface CommandConfig
              -extends CommandConfigProvider
              +extends CommandConfigProvider
            • @@ -117,28 +140,33 @@ extends
            • +
              +
            • @@ -146,51 +174,56 @@ extends
            • +
              +
            • +
              + diff --git a/docs/acf-jda/co/aikar/commands/CommandConfigProvider.html b/docs/acf-jda/co/aikar/commands/CommandConfigProvider.html index c32f2d5e..fa3f8b76 100644 --- a/docs/acf-jda/co/aikar/commands/CommandConfigProvider.html +++ b/docs/acf-jda/co/aikar/commands/CommandConfigProvider.html @@ -1,12 +1,21 @@ - + - CommandConfigProvider (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Interface CommandConfigProvider

              @@ -100,14 +124,13 @@ var activeTableTab = "activeTableTab";
            • All Known Subinterfaces:
              -
              CommandConfig
              +
              CommandConfig
              All Known Implementing Classes:
              -
              JDACommandConfig
              +
              JDACommandConfig

              -
              public interface CommandConfigProvider
            • @@ -116,24 +139,28 @@ var activeTableTab = "activeTableTab";
              @@ -141,37 +168,42 @@ var activeTableTab = "activeTableTab"; +
              + diff --git a/docs/acf-jda/co/aikar/commands/CommandPermissionResolver.html b/docs/acf-jda/co/aikar/commands/CommandPermissionResolver.html index 74430c78..3c9e650e 100644 --- a/docs/acf-jda/co/aikar/commands/CommandPermissionResolver.html +++ b/docs/acf-jda/co/aikar/commands/CommandPermissionResolver.html @@ -1,12 +1,21 @@ - + - CommandPermissionResolver (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Interface CommandPermissionResolver

              @@ -100,10 +124,9 @@ var activeTableTab = "activeTableTab";
            • All Known Implementing Classes:
              -
              JDACommandPermissionResolver
              +
              JDACommandPermissionResolver

              -
              public interface CommandPermissionResolver
            • @@ -112,26 +135,30 @@ var activeTableTab = "activeTableTab";
              @@ -139,39 +166,44 @@ var activeTableTab = "activeTableTab"; +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDACommandCompletions.html b/docs/acf-jda/co/aikar/commands/JDACommandCompletions.html index dab8c4cf..d19c46b1 100644 --- a/docs/acf-jda/co/aikar/commands/JDACommandCompletions.html +++ b/docs/acf-jda/co/aikar/commands/JDACommandCompletions.html @@ -1,12 +1,21 @@ - + - JDACommandCompletions (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDACommandCompletions

                -
              • java.lang.Object
              • +
              • java.lang.Object
                • co.aikar.commands.CommandCompletions<co.aikar.commands.CommandCompletionContext<?>>
                • @@ -112,7 +136,6 @@ var activeTableTab = "activeTableTab";

                  • -
                    public class JDACommandCompletions
                     extends co.aikar.commands.CommandCompletions<co.aikar.commands.CommandCompletionContext<?>>
                  • @@ -122,13 +145,14 @@ extends co.aikar.commands.CommandCompletions<co.aikar.commands.CommandComplet
                    • +
                        -
                      • +
                      • Nested Class Summary

                          -
                        • +
                        • Nested classes/interfaces inherited from class co.aikar.commands.CommandCompletions

                          @@ -136,62 +160,72 @@ extends co.aikar.commands.CommandCompletions<co.aikar.commands.CommandComplet
                      +
                      +
                        -
                      • +
                      • Constructor Summary

                        - +
                        - + + - + +
                        Constructors 
                        Constructor and DescriptionConstructorDescription
                        JDACommandCompletions(co.aikar.commands.CommandManager manager) JDACommandCompletions​(co.aikar.commands.CommandManager manager) 
                      +
                      +
                      +
              @@ -199,35 +233,38 @@ extends co.aikar.commands.CommandCompletions<co.aikar.commands.CommandComplet
              • +
                +
                +
                  -
                • +
                • Method Detail

                  - +
                  • registerCompletion

                    -
                    public co.aikar.commands.CommandCompletions.CommandCompletionHandler registerCompletion(String id,
                    +
                    public co.aikar.commands.CommandCompletions.CommandCompletionHandler registerCompletion​(String id,
                                                                                                             co.aikar.commands.CommandCompletions.CommandCompletionHandler<co.aikar.commands.CommandCompletionContext<?>> handler)
                    Overrides:
                    @@ -235,13 +272,13 @@ extends co.aikar.commands.CommandCompletions<co.aikar.commands.CommandComplet
                  - +
                  • registerAsyncCompletion

                    -
                    public co.aikar.commands.CommandCompletions.CommandCompletionHandler registerAsyncCompletion(String id,
                    +
                    public co.aikar.commands.CommandCompletions.CommandCompletionHandler registerAsyncCompletion​(String id,
                                                                                                                  co.aikar.commands.CommandCompletions.AsyncCommandCompletionHandler<co.aikar.commands.CommandCompletionContext<?>> handler)
                    Overrides:
                    @@ -251,21 +288,25 @@ extends co.aikar.commands.CommandCompletions<co.aikar.commands.CommandComplet
                +
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDACommandConfig.html b/docs/acf-jda/co/aikar/commands/JDACommandConfig.html index 1e361a3f..fa89b979 100644 --- a/docs/acf-jda/co/aikar/commands/JDACommandConfig.html +++ b/docs/acf-jda/co/aikar/commands/JDACommandConfig.html @@ -1,12 +1,21 @@ - + - JDACommandConfig (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDACommandConfig

              @@ -122,74 +145,86 @@ implements
            • +
              +
              +
              +
              +
              +
            • @@ -197,30 +232,33 @@ implements
            • +
              +
              +
            • +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDACommandContexts.html b/docs/acf-jda/co/aikar/commands/JDACommandContexts.html index a7a5950a..646e596c 100644 --- a/docs/acf-jda/co/aikar/commands/JDACommandContexts.html +++ b/docs/acf-jda/co/aikar/commands/JDACommandContexts.html @@ -1,12 +1,21 @@ - + - JDACommandContexts (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDACommandContexts

              @@ -116,13 +139,14 @@ extends co.aikar.commands.CommandContexts<
            • +
              +
              +
            • @@ -176,37 +207,42 @@ extends co.aikar.commands.CommandContexts<
            • +
              +
            • +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDACommandEvent.html b/docs/acf-jda/co/aikar/commands/JDACommandEvent.html index 7fad311b..eb18956e 100644 --- a/docs/acf-jda/co/aikar/commands/JDACommandEvent.html +++ b/docs/acf-jda/co/aikar/commands/JDACommandEvent.html @@ -1,12 +1,21 @@ - + - JDACommandEvent (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDACommandEvent

              @@ -211,152 +250,159 @@ implements co.aikar.commands.CommandIssuer
              • +
                +
                +
                  -
                • +
                • Method Detail

                  - +
                  • getEvent

                    -
                    public net.dv8tion.jda.core.events.message.MessageReceivedEvent getEvent()
                    +
                    public net.dv8tion.jda.core.events.message.MessageReceivedEvent getEvent()
                  - +
                  • getIssuer

                    -
                    public net.dv8tion.jda.core.events.message.MessageReceivedEvent getIssuer()
                    +
                    public net.dv8tion.jda.core.events.message.MessageReceivedEvent getIssuer()
                    Specified by:
                    getIssuer in interface co.aikar.commands.CommandIssuer
                  - +
                  • getManager

                    -
                    public co.aikar.commands.CommandManager getManager()
                    +
                    public co.aikar.commands.CommandManager getManager()
                    Specified by:
                    getManager in interface co.aikar.commands.CommandIssuer
                  - +
                  • isPlayer

                    -
                    public boolean isPlayer()
                    +
                    public boolean isPlayer()
                    Specified by:
                    isPlayer in interface co.aikar.commands.CommandIssuer
                  - +
                  • getUniqueId

                    -
                    @NotNull
                    -public @NotNull UUID getUniqueId()
                    +
                    @NotNull
                    +public @NotNull UUID getUniqueId()
                    Specified by:
                    getUniqueId in interface co.aikar.commands.CommandIssuer
                  - +
                  • hasPermission

                    -
                    public boolean hasPermission(String permission)
                    +
                    public boolean hasPermission​(String permission)
                    Specified by:
                    hasPermission in interface co.aikar.commands.CommandIssuer
                  - + - +
                  • sendMessage

                    -
                    public void sendMessage(net.dv8tion.jda.core.entities.Message message)
                    +
                    public void sendMessage​(net.dv8tion.jda.core.entities.Message message)
                  - +
                  • sendMessage

                    -
                    public void sendMessage(net.dv8tion.jda.core.entities.MessageEmbed message)
                    +
                    public void sendMessage​(net.dv8tion.jda.core.entities.MessageEmbed message)
                +
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDACommandExecutionContext.html b/docs/acf-jda/co/aikar/commands/JDACommandExecutionContext.html index 54841594..f0bb9e01 100644 --- a/docs/acf-jda/co/aikar/commands/JDACommandExecutionContext.html +++ b/docs/acf-jda/co/aikar/commands/JDACommandExecutionContext.html @@ -1,12 +1,21 @@ - + - JDACommandExecutionContext (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDACommandExecutionContext

              @@ -116,13 +139,14 @@ extends co.aikar.commands.CommandExecutionContext<
            • +
                -
              • +
              • Field Summary

                  -
                • +
                • Fields inherited from class co.aikar.commands.CommandExecutionContext

                  @@ -130,43 +154,49 @@ extends co.aikar.commands.CommandExecutionContext<
                    -
                  • +
                  • Method Summary

                      -
                    • +
                    • Methods inherited from class co.aikar.commands.CommandExecutionContext

                      canOverridePlayerContext, getAnnotation, getAnnotationValue, getAnnotationValue, getArgs, getBooleanFlagValue, getBooleanFlagValue, getCmd, getDoubleFlagValue, getFirstArg, getFlags, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFloatFlagValue, getIndex, getIntFlagValue, getIssuer, getLastArg, getLongFlagValue, getNumParams, getParam, getParameterPermissions, getPassedArgs, getResolvedArg, getResolvedArg, getResolvedArg, hasAnnotation, hasFlag, isLastArg, isOptional, joinArgs, joinArgs, popFirstArg, popLastArg
                  +
            • +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDACommandManager.html b/docs/acf-jda/co/aikar/commands/JDACommandManager.html index 06aa5e5c..4b8bb5a0 100644 --- a/docs/acf-jda/co/aikar/commands/JDACommandManager.html +++ b/docs/acf-jda/co/aikar/commands/JDACommandManager.html @@ -1,12 +1,21 @@ - + - JDACommandManager (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDACommandManager

              @@ -122,36 +145,42 @@ extends co.aikar.commands.CommandManager<net.dv8tion.jda.core.events.message. @@ -327,388 +390,397 @@ extends co.aikar.commands.CommandManager<net.dv8tion.jda.core.events.message. +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDACommandPermissionResolver.html b/docs/acf-jda/co/aikar/commands/JDACommandPermissionResolver.html index 97ecf6f1..2b83c553 100644 --- a/docs/acf-jda/co/aikar/commands/JDACommandPermissionResolver.html +++ b/docs/acf-jda/co/aikar/commands/JDACommandPermissionResolver.html @@ -1,12 +1,21 @@ - + - JDACommandPermissionResolver (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDACommandPermissionResolver

              @@ -122,50 +145,58 @@ implements
            • +
              +
              +
              +
            • @@ -173,60 +204,67 @@ implements
            • +
              +
              +
              +
            • +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDAConditionContext.html b/docs/acf-jda/co/aikar/commands/JDAConditionContext.html index 15123e37..14e5f96f 100644 --- a/docs/acf-jda/co/aikar/commands/JDAConditionContext.html +++ b/docs/acf-jda/co/aikar/commands/JDAConditionContext.html @@ -1,12 +1,21 @@ - + - JDAConditionContext (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDAConditionContext

              @@ -116,42 +139,47 @@ extends co.aikar.commands.ConditionContext<
            • +
              +
            • +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDAListener.html b/docs/acf-jda/co/aikar/commands/JDAListener.html index 7fb58f9b..a18632b5 100644 --- a/docs/acf-jda/co/aikar/commands/JDAListener.html +++ b/docs/acf-jda/co/aikar/commands/JDAListener.html @@ -1,12 +1,21 @@ - + - JDAListener (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDAListener

                -
              • java.lang.Object
              • +
              • java.lang.Object
                • net.dv8tion.jda.core.hooks.ListenerAdapter
                • @@ -113,10 +137,9 @@ var activeTableTab = "activeTableTab";
                • All Implemented Interfaces:
                  -
                  net.dv8tion.jda.core.hooks.EventListener
                  +
                  net.dv8tion.jda.core.hooks.EventListener

                  -
                  public class JDAListener
                   extends net.dv8tion.jda.core.hooks.ListenerAdapter
                • @@ -126,42 +149,47 @@ extends net.dv8tion.jda.core.hooks.ListenerAdapter
                  • +
                      -
                    • +
                    • Method Summary

                      - +
                      - + + - + + - + +
                      All Methods Instance Methods Concrete Methods 
                      Modifier and TypeMethod and DescriptionMethodDescription
                      voidonMessageReceived(net.dv8tion.jda.core.events.message.MessageReceivedEvent event) onMessageReceived​(net.dv8tion.jda.core.events.message.MessageReceivedEvent event) 
                      voidonReady(net.dv8tion.jda.core.events.ReadyEvent event) onReady​(net.dv8tion.jda.core.events.ReadyEvent event) 
                        -
                      • +
                      • Methods inherited from class net.dv8tion.jda.core.hooks.ListenerAdapter

                        -onCallCreate, onCallDelete, onCallUpdateRegion, onCallUpdateRingingUsers, onCallVoiceJoin, onCallVoiceLeave, onCallVoiceSelfDeafen, onCallVoiceSelfMute, onCategoryCreate, onCategoryDelete, onCategoryUpdateName, onCategoryUpdatePermissions, onCategoryUpdatePosition, onDisconnect, onEmoteAdded, onEmoteRemoved, onEmoteUpdateName, onEmoteUpdateRoles, onEvent, onException, onFriendAdded, onFriendRemoved, onFriendRequestCanceled, onFriendRequestIgnored, onFriendRequestReceived, onFriendRequestSent, onGenericCall, onGenericCallUpdate, onGenericCallVoice, onGenericCategory, onGenericCategoryUpdate, onGenericEmote, onGenericEmoteUpdate, onGenericEvent, onGenericGroup, onGenericGroupMessage, onGenericGroupMessageReaction, onGenericGroupUpdate, onGenericGuild, onGenericGuildMember, onGenericGuildMessage, onGenericGuildMessageReaction, onGenericGuildUpdate, onGenericGuildVoice, onGenericMessage, onGenericMessageReaction, onGenericPrivateMessage, onGenericPrivateMessageReaction, onGenericRelationship, onGenericRelationshipAdd, onGenericRelationshipRemove, onGenericRole, onGenericRoleUpdate, onGenericSelfUpdate, onGenericTextChannel, onGenericTextChannelUpdate, onGenericUser, onGenericUserPresence, onGenericVoiceChannel, onGenericVoiceChannelUpdate, onGroupJoin, onGroupLeave, onGroupMessageDelete, onGroupMessageEmbed, onGroupMessageReactionAdd, onGroupMessageReactionRemove, onGroupMessageReactionRemoveAll, onGroupMessageReceived, onGroupMessageUpdate, onGroupUpdateIcon, onGroupUpdateName, onGroupUpdateOwner, onGroupUserJoin, onGroupUserLeave, onGuildAvailable, onGuildBan, onGuildJoin, onGuildLeave, onGuildMemberJoin, onGuildMemberLeave, onGuildMemberNickChange, onGuildMemberRoleAdd, onGuildMemberRoleRemove, onGuildMessageDelete, onGuildMessageEmbed, onGuildMessageReactionAdd, onGuildMessageReactionRemove, onGuildMessageReactionRemoveAll, onGuildMessageReceived, onGuildMessageUpdate, onGuildUnavailable, onGuildUnban, onGuildUpdateAfkChannel, onGuildUpdateAfkTimeout, onGuildUpdateExplicitContentLevel, onGuildUpdateFeatures, onGuildUpdateIcon, onGuildUpdateMFALevel, onGuildUpdateName, onGuildUpdateNotificationLevel, onGuildUpdateOwner, onGuildUpdateRegion, onGuildUpdateSplash, onGuildUpdateSystemChannel, onGuildUpdateVerificationLevel, onGuildVoiceDeafen, onGuildVoiceGuildDeafen, onGuildVoiceGuildMute, onGuildVoiceJoin, onGuildVoiceLeave, onGuildVoiceMove, onGuildVoiceMute, onGuildVoiceSelfDeafen, onGuildVoiceSelfMute, onGuildVoiceSuppress, onGuildVoiceUpdate, onHttpRequest, onMessageBulkDelete, onMessageDelete, onMessageEmbed, onMessageReactionAdd, onMessageReactionRemove, onMessageReactionRemoveAll, onMessageUpdate, onPrivateChannelCreate, onPrivateChannelDelete, onPrivateMessageDelete, onPrivateMessageEmbed, onPrivateMessageReactionAdd, onPrivateMessageReactionRemove, onPrivateMessageReceived, onPrivateMessageUpdate, onReconnect, onResume, onRoleCreate, onRoleDelete, onRoleUpdateColor, onRoleUpdateHoisted, onRoleUpdateMentionable, onRoleUpdateName, onRoleUpdatePermissions, onRoleUpdatePosition, onSelfUpdateAvatar, onSelfUpdateEmail, onSelfUpdateMFA, onSelfUpdateName, onSelfUpdateVerified, onShutdown, onStatusChange, onTextChannelCreate, onTextChannelDelete, onTextChannelUpdateName, onTextChannelUpdateNSFW, onTextChannelUpdateParent, onTextChannelUpdatePermissions, onTextChannelUpdatePosition, onTextChannelUpdateTopic, onUnavailableGuildJoined, onUserAvatarUpdate, onUserBlocked, onUserGameUpdate, onUserNameUpdate, onUserOnlineStatusUpdate, onUserTyping, onUserUnblocked, onVoiceChannelCreate, onVoiceChannelDelete, onVoiceChannelUpdateBitrate, onVoiceChannelUpdateName, onVoiceChannelUpdateParent, onVoiceChannelUpdatePermissions, onVoiceChannelUpdatePosition, onVoiceChannelUpdateUserLimit
                      • +onCallCreate, onCallDelete, onCallUpdateRegion, onCallUpdateRingingUsers, onCallVoiceJoin, onCallVoiceLeave, onCallVoiceSelfDeafen, onCallVoiceSelfMute, onCategoryCreate, onCategoryDelete, onCategoryUpdateName, onCategoryUpdatePermissions, onCategoryUpdatePosition, onDisconnect, onEmoteAdded, onEmoteRemoved, onEmoteUpdateName, onEmoteUpdateRoles, onEvent, onException, onFriendAdded, onFriendRemoved, onFriendRequestCanceled, onFriendRequestIgnored, onFriendRequestReceived, onFriendRequestSent, onGenericCall, onGenericCallUpdate, onGenericCallVoice, onGenericCategory, onGenericCategoryUpdate, onGenericEmote, onGenericEmoteUpdate, onGenericEvent, onGenericGroup, onGenericGroupMessage, onGenericGroupMessageReaction, onGenericGroupUpdate, onGenericGuild, onGenericGuildMember, onGenericGuildMessage, onGenericGuildMessageReaction, onGenericGuildUpdate, onGenericGuildVoice, onGenericMessage, onGenericMessageReaction, onGenericPrivateMessage, onGenericPrivateMessageReaction, onGenericRelationship, onGenericRelationshipAdd, onGenericRelationshipRemove, onGenericRole, onGenericRoleUpdate, onGenericSelfUpdate, onGenericTextChannel, onGenericTextChannelUpdate, onGenericUpdate, onGenericUser, onGenericUserPresence, onGenericVoiceChannel, onGenericVoiceChannelUpdate, onGroupJoin, onGroupLeave, onGroupMessageDelete, onGroupMessageEmbed, onGroupMessageReactionAdd, onGroupMessageReactionRemove, onGroupMessageReactionRemoveAll, onGroupMessageReceived, onGroupMessageUpdate, onGroupUpdateIcon, onGroupUpdateName, onGroupUpdateOwner, onGroupUserJoin, onGroupUserLeave, onGuildAvailable, onGuildBan, onGuildJoin, onGuildLeave, onGuildMemberJoin, onGuildMemberLeave, onGuildMemberNickChange, onGuildMemberRoleAdd, onGuildMemberRoleRemove, onGuildMessageDelete, onGuildMessageEmbed, onGuildMessageReactionAdd, onGuildMessageReactionRemove, onGuildMessageReactionRemoveAll, onGuildMessageReceived, onGuildMessageUpdate, onGuildReady, onGuildUnavailable, onGuildUnban, onGuildUpdateAfkChannel, onGuildUpdateAfkTimeout, onGuildUpdateExplicitContentLevel, onGuildUpdateFeatures, onGuildUpdateIcon, onGuildUpdateMFALevel, onGuildUpdateName, onGuildUpdateNotificationLevel, onGuildUpdateOwner, onGuildUpdateRegion, onGuildUpdateSplash, onGuildUpdateSystemChannel, onGuildUpdateVerificationLevel, onGuildVoiceDeafen, onGuildVoiceGuildDeafen, onGuildVoiceGuildMute, onGuildVoiceJoin, onGuildVoiceLeave, onGuildVoiceMove, onGuildVoiceMute, onGuildVoiceSelfDeafen, onGuildVoiceSelfMute, onGuildVoiceSuppress, onGuildVoiceUpdate, onHttpRequest, onMessageBulkDelete, onMessageDelete, onMessageEmbed, onMessageReactionAdd, onMessageReactionRemove, onMessageReactionRemoveAll, onMessageUpdate, onPrivateChannelCreate, onPrivateChannelDelete, onPrivateMessageDelete, onPrivateMessageEmbed, onPrivateMessageReactionAdd, onPrivateMessageReactionRemove, onPrivateMessageReceived, onPrivateMessageUpdate, onReconnect, onResume, onRoleCreate, onRoleDelete, onRoleUpdateColor, onRoleUpdateHoisted, onRoleUpdateMentionable, onRoleUpdateName, onRoleUpdatePermissions, onRoleUpdatePosition, onSelfUpdateAvatar, onSelfUpdateEmail, onSelfUpdateMFA, onSelfUpdateName, onSelfUpdateVerified, onShutdown, onStatusChange, onTextChannelCreate, onTextChannelDelete, onTextChannelUpdateName, onTextChannelUpdateNSFW, onTextChannelUpdateParent, onTextChannelUpdatePermissions, onTextChannelUpdatePosition, onTextChannelUpdateSlowmode, onTextChannelUpdateTopic, onUnavailableGuildJoined, onUserBlocked, onUserTyping, onUserUnblocked, onUserUpdateAvatar, onUserUpdateDiscriminator, onUserUpdateGame, onUserUpdateName, onUserUpdateOnlineStatus, onVoiceChannelCreate, onVoiceChannelDelete, onVoiceChannelUpdateBitrate, onVoiceChannelUpdateName, onVoiceChannelUpdateParent, onVoiceChannelUpdatePermissions, onVoiceChannelUpdatePosition, onVoiceChannelUpdateUserLimit
                    +
              @@ -169,31 +197,32 @@ extends net.dv8tion.jda.core.hooks.ListenerAdapter
              • +
                  -
                • +
                • Method Detail

                  - +
                  • onMessageReceived

                    -
                    public void onMessageReceived(net.dv8tion.jda.core.events.message.MessageReceivedEvent event)
                    +
                    public void onMessageReceived​(net.dv8tion.jda.core.events.message.MessageReceivedEvent event)
                    Overrides:
                    onMessageReceived in class net.dv8tion.jda.core.hooks.ListenerAdapter
                  - +
                  • onReady

                    -
                    public void onReady(net.dv8tion.jda.core.events.ReadyEvent event)
                    +
                    public void onReady​(net.dv8tion.jda.core.events.ReadyEvent event)
                    Overrides:
                    onReady in class net.dv8tion.jda.core.hooks.ListenerAdapter
                    @@ -202,21 +231,25 @@ extends net.dv8tion.jda.core.hooks.ListenerAdapter
                +
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDALocales.html b/docs/acf-jda/co/aikar/commands/JDALocales.html index a57a5e1b..52caed63 100644 --- a/docs/acf-jda/co/aikar/commands/JDALocales.html +++ b/docs/acf-jda/co/aikar/commands/JDALocales.html @@ -1,12 +1,21 @@ - + - JDALocales (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDALocales

              @@ -176,37 +207,42 @@ extends co.aikar.commands.Locales
              • +
                  -
                • +
                • Constructor Detail

                  - +
                  • JDALocales

                    -
                    public JDALocales(co.aikar.commands.CommandManager manager)
                    +
                    public JDALocales​(co.aikar.commands.CommandManager manager)
                +
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/JDAMessageFormatter.html b/docs/acf-jda/co/aikar/commands/JDAMessageFormatter.html index b48df8d7..4ec6d4ae 100644 --- a/docs/acf-jda/co/aikar/commands/JDAMessageFormatter.html +++ b/docs/acf-jda/co/aikar/commands/JDAMessageFormatter.html @@ -1,12 +1,21 @@ - + - JDAMessageFormatter (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDAMessageFormatter

              @@ -116,44 +139,50 @@ extends co.aikar.commands.MessageFormatter<
            • +
              +
              +
              +
            • @@ -161,12 +190,13 @@ extends co.aikar.commands.MessageFormatter<
            • +
              +
            • + diff --git a/docs/acf-jda/co/aikar/commands/JDARootCommand.html b/docs/acf-jda/co/aikar/commands/JDARootCommand.html index 918f420a..8dd741c2 100644 --- a/docs/acf-jda/co/aikar/commands/JDARootCommand.html +++ b/docs/acf-jda/co/aikar/commands/JDARootCommand.html @@ -1,12 +1,21 @@ - + - JDARootCommand (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands
              +

              Class JDARootCommand

              @@ -181,83 +213,84 @@ implements co.aikar.commands.RootCommand
              • +
                  -
                • +
                • Method Detail

                  - +
                  • addChild

                    -
                    public void addChild(co.aikar.commands.BaseCommand command)
                    +
                    public void addChild​(co.aikar.commands.BaseCommand command)
                    Specified by:
                    addChild in interface co.aikar.commands.RootCommand
                  - +
                  • getManager

                    -
                    public co.aikar.commands.CommandManager getManager()
                    +
                    public co.aikar.commands.CommandManager getManager()
                    Specified by:
                    getManager in interface co.aikar.commands.RootCommand
                  - +
                  • getSubCommands

                    -
                    public com.google.common.collect.SetMultimap<String,co.aikar.commands.RegisteredCommand> getSubCommands()
                    +
                    public com.google.common.collect.SetMultimap<String,​co.aikar.commands.RegisteredCommand> getSubCommands()
                    Specified by:
                    getSubCommands in interface co.aikar.commands.RootCommand
                  - +
                  • getChildren

                    -
                    public List<co.aikar.commands.BaseCommand> getChildren()
                    +
                    public List<co.aikar.commands.BaseCommand> getChildren()
                    Specified by:
                    getChildren in interface co.aikar.commands.RootCommand
                  - + - +
                  • getDefCommand

                    -
                    public co.aikar.commands.BaseCommand getDefCommand()
                    +
                    public co.aikar.commands.BaseCommand getDefCommand()
                    Specified by:
                    getDefCommand in interface co.aikar.commands.RootCommand
                    @@ -266,21 +299,25 @@ implements co.aikar.commands.RootCommand
                +
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/annotation/Author.html b/docs/acf-jda/co/aikar/commands/annotation/Author.html index d0c4feb9..0445250c 100644 --- a/docs/acf-jda/co/aikar/commands/annotation/Author.html +++ b/docs/acf-jda/co/aikar/commands/annotation/Author.html @@ -1,12 +1,21 @@ - + - Author (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              -
              co.aikar.commands.annotation
              +

              Annotation Type Author

              @@ -91,11 +115,10 @@

              • -
                -
                @Target(value=PARAMETER)
                - @Retention(value=RUNTIME)
                -public @interface Author
                -
                The Author annotation is to define whether the parameter should be the author object from the event or +
                @Target(PARAMETER)
                +@Retention(RUNTIME)
                +public @interface Author
                +
                The Author annotation is to define whether the parameter should be the author object from the event or parsed from the user's input.

                Using this on a User/Member will fetch the author and otherwise it'll parse the input. @@ -104,17 +127,20 @@ public @interface +

                +

                Copyright © 2020. All rights reserved.

                + diff --git a/docs/acf-jda/co/aikar/commands/annotation/CrossGuild.html b/docs/acf-jda/co/aikar/commands/annotation/CrossGuild.html index 26f8e7a4..163a42e4 100644 --- a/docs/acf-jda/co/aikar/commands/annotation/CrossGuild.html +++ b/docs/acf-jda/co/aikar/commands/annotation/CrossGuild.html @@ -1,12 +1,21 @@ - + - CrossGuild (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +
                -
                co.aikar.commands.annotation
                +

                Annotation Type CrossGuild

                @@ -91,11 +115,10 @@

                • -
                  -
                  @Target(value=PARAMETER)
                  - @Retention(value=RUNTIME)
                  -public @interface CrossGuild
                  -
                  The CrossGuild annotation is to define whether the parameter should be guild-specific or global. +
                  @Target(PARAMETER)
                  +@Retention(RUNTIME)
                  +public @interface CrossGuild
                  +
                  The CrossGuild annotation is to define whether the parameter should be guild-specific or global.

                  If a supported parameter is marked with the CrossGuild annotation, the parameter will be filled from a global perspective (i.e., all of the guilds the bot is connected to). Otherwise, the parameter will @@ -105,17 +128,20 @@ public @interface +

                  +

                  Copyright © 2020. All rights reserved.

                  + diff --git a/docs/acf-jda/co/aikar/commands/annotation/SelfUser.html b/docs/acf-jda/co/aikar/commands/annotation/SelfUser.html index fda4ec57..e0ae2f9d 100644 --- a/docs/acf-jda/co/aikar/commands/annotation/SelfUser.html +++ b/docs/acf-jda/co/aikar/commands/annotation/SelfUser.html @@ -1,12 +1,21 @@ - + - SelfUser (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                  + +
                  +
                  -
                  co.aikar.commands.annotation
                  +

                  Annotation Type SelfUser

                  @@ -91,27 +115,29 @@
                  +
                + diff --git a/docs/acf-jda/co/aikar/commands/annotation/class-use/Author.html b/docs/acf-jda/co/aikar/commands/annotation/class-use/Author.html index 5b53a093..71bd3264 100644 --- a/docs/acf-jda/co/aikar/commands/annotation/class-use/Author.html +++ b/docs/acf-jda/co/aikar/commands/annotation/class-use/Author.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.Author (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.annotation.Author

                No usage of co.aikar.commands.annotation.Author
                +
                + diff --git a/docs/acf-jda/co/aikar/commands/annotation/class-use/CrossGuild.html b/docs/acf-jda/co/aikar/commands/annotation/class-use/CrossGuild.html index 80c548cb..69503ae9 100644 --- a/docs/acf-jda/co/aikar/commands/annotation/class-use/CrossGuild.html +++ b/docs/acf-jda/co/aikar/commands/annotation/class-use/CrossGuild.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.CrossGuild (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.annotation.CrossGuild

                No usage of co.aikar.commands.annotation.CrossGuild
                +
                + diff --git a/docs/acf-jda/co/aikar/commands/annotation/class-use/SelfUser.html b/docs/acf-jda/co/aikar/commands/annotation/class-use/SelfUser.html index ea16d87f..00be1090 100644 --- a/docs/acf-jda/co/aikar/commands/annotation/class-use/SelfUser.html +++ b/docs/acf-jda/co/aikar/commands/annotation/class-use/SelfUser.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.annotation.SelfUser (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Uses of Class
                co.aikar.commands.annotation.SelfUser

                No usage of co.aikar.commands.annotation.SelfUser
                +
                + diff --git a/docs/acf-jda/co/aikar/commands/annotation/package-summary.html b/docs/acf-jda/co/aikar/commands/annotation/package-summary.html index 583886fb..7cd60170 100644 --- a/docs/acf-jda/co/aikar/commands/annotation/package-summary.html +++ b/docs/acf-jda/co/aikar/commands/annotation/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.annotation (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                + +
                +

                Package co.aikar.commands.annotation

                • - +
                  @@ -82,22 +106,22 @@ - + - + - + @@ -106,16 +130,19 @@ + + diff --git a/docs/acf-jda/co/aikar/commands/annotation/package-tree.html b/docs/acf-jda/co/aikar/commands/annotation/package-tree.html index c2da9381..9e6c95c1 100644 --- a/docs/acf-jda/co/aikar/commands/annotation/package-tree.html +++ b/docs/acf-jda/co/aikar/commands/annotation/package-tree.html @@ -1,12 +1,21 @@ - + -co.aikar.commands.annotation Class Hierarchy (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                  + +
                  +

                  Hierarchy For Package co.aikar.commands.annotation

                  Package Hierarchies: @@ -76,23 +100,28 @@
                  +

                  Annotation Type Hierarchy

                  +
                  +
                  + diff --git a/docs/acf-jda/co/aikar/commands/annotation/package-use.html b/docs/acf-jda/co/aikar/commands/annotation/package-use.html index e79041ee..23daadd5 100644 --- a/docs/acf-jda/co/aikar/commands/annotation/package-use.html +++ b/docs/acf-jda/co/aikar/commands/annotation/package-use.html @@ -1,12 +1,21 @@ - + -Uses of Package co.aikar.commands.annotation (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                  + +
                  +

                  Uses of Package
                  co.aikar.commands.annotation

                  No usage of co.aikar.commands.annotation
                  +
                  + diff --git a/docs/acf-jda/co/aikar/commands/class-use/CommandConfig.html b/docs/acf-jda/co/aikar/commands/class-use/CommandConfig.html index 36bb0bb4..01cef027 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/CommandConfig.html +++ b/docs/acf-jda/co/aikar/commands/class-use/CommandConfig.html @@ -1,12 +1,21 @@ - + -Uses of Interface co.aikar.commands.CommandConfig (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
                  + +
                  +

                  Uses of Interface
                  co.aikar.commands.CommandConfig

                  • -
                  Annotation Types Summary 
                  Annotation Type
                  AuthorAuthor -
                  The Author annotation is to define whether the parameter should be the author object from the event or +
                  The Author annotation is to define whether the parameter should be the author object from the event or parsed from the user's input.
                  CrossGuildCrossGuild -
                  The CrossGuild annotation is to define whether the parameter should be guild-specific or global.
                  +
                  The CrossGuild annotation is to define whether the parameter should be guild-specific or global.
                  SelfUserSelfUser -
                  The SelfUser annotation is to define whether the parameter should be represented by JDA's user object +
                  The SelfUser annotation is to define whether the parameter should be represented by JDA's user object or if it should be parsed from command input.
                  - +
                  Packages that use CommandConfig 
                  + - + @@ -90,78 +114,92 @@
                • Packages that use CommandConfig 
                  Package Description
                  co.aikar.commandsco.aikar.commands  
                  - +

                  Uses of CommandConfig in co.aikar.commands

                  +
                  Classes in co.aikar.commands that implement CommandConfig 
                  + - + + - + +
                  Classes in co.aikar.commands that implement CommandConfig 
                  Modifier and TypeClass and DescriptionClassDescription
                  class JDACommandConfig JDACommandConfig 
                  - - +
                  Methods in co.aikar.commands that return CommandConfig 
                  + - + + - - + + + - - + + + - - + + +
                  Methods in co.aikar.commands that return CommandConfig 
                  Modifier and TypeMethod and DescriptionMethodDescription
                  CommandConfigJDACommandManager.getDefaultConfig() CommandConfigJDACommandManager.getDefaultConfig() 
                  CommandConfigCommandConfigProvider.provide(net.dv8tion.jda.core.events.message.MessageReceivedEvent event) default CommandConfigCommandConfig.provide​(net.dv8tion.jda.core.events.message.MessageReceivedEvent event) 
                  default CommandConfigCommandConfig.provide(net.dv8tion.jda.core.events.message.MessageReceivedEvent event) CommandConfigCommandConfigProvider.provide​(net.dv8tion.jda.core.events.message.MessageReceivedEvent event) 
                  - - +
                  Methods in co.aikar.commands with parameters of type CommandConfig 
                  + - + + - - + + + - + +
                  Methods in co.aikar.commands with parameters of type CommandConfig 
                  Modifier and TypeMethod and DescriptionMethodDescription
                  JDAOptionsJDAOptions.defaultConfig(@NotNull CommandConfig defaultConfig) JDAOptionsJDAOptions.defaultConfig​(@NotNull CommandConfig defaultConfig) 
                  voidJDACommandManager.setDefaultConfig(@NotNull CommandConfig defaultConfig) JDACommandManager.setDefaultConfig​(@NotNull CommandConfig defaultConfig) 
                  +
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/CommandConfigProvider.html b/docs/acf-jda/co/aikar/commands/class-use/CommandConfigProvider.html index 62f9d08b..f87ec837 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/CommandConfigProvider.html +++ b/docs/acf-jda/co/aikar/commands/class-use/CommandConfigProvider.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.CommandConfigProvider (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Interface
              co.aikar.commands.CommandConfigProvider

              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/CommandPermissionResolver.html b/docs/acf-jda/co/aikar/commands/class-use/CommandPermissionResolver.html index 883cdf62..3b4eaf88 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/CommandPermissionResolver.html +++ b/docs/acf-jda/co/aikar/commands/class-use/CommandPermissionResolver.html @@ -1,12 +1,21 @@ - + - Uses of Interface co.aikar.commands.CommandPermissionResolver (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Interface
              co.aikar.commands.CommandPermissionResolver

              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDACommandCompletions.html b/docs/acf-jda/co/aikar/commands/class-use/JDACommandCompletions.html index d640c0d6..0a7d2c9f 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDACommandCompletions.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDACommandCompletions.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDACommandCompletions (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDACommandCompletions

              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDACommandConfig.html b/docs/acf-jda/co/aikar/commands/class-use/JDACommandConfig.html index 12eaa39b..93be74e0 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDACommandConfig.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDACommandConfig.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDACommandConfig (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDACommandConfig

              No usage of co.aikar.commands.JDACommandConfig
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDACommandContexts.html b/docs/acf-jda/co/aikar/commands/class-use/JDACommandContexts.html index 10ae1452..93bc348f 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDACommandContexts.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDACommandContexts.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDACommandContexts (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDACommandContexts

              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDACommandEvent.html b/docs/acf-jda/co/aikar/commands/class-use/JDACommandEvent.html index 2d0fab82..1e9f4599 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDACommandEvent.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDACommandEvent.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDACommandEvent (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDACommandEvent

              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDACommandExecutionContext.html b/docs/acf-jda/co/aikar/commands/class-use/JDACommandExecutionContext.html index feeb4773..9028ca7a 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDACommandExecutionContext.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDACommandExecutionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDACommandExecutionContext (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDACommandExecutionContext

              No usage of co.aikar.commands.JDACommandExecutionContext
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDACommandManager.html b/docs/acf-jda/co/aikar/commands/class-use/JDACommandManager.html index 7d7d3cea..a5464c88 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDACommandManager.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDACommandManager.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDACommandManager (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDACommandManager

              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDACommandPermissionResolver.html b/docs/acf-jda/co/aikar/commands/class-use/JDACommandPermissionResolver.html index 98a844c8..19f73baa 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDACommandPermissionResolver.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDACommandPermissionResolver.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDACommandPermissionResolver (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDACommandPermissionResolver

              No usage of co.aikar.commands.JDACommandPermissionResolver
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDAConditionContext.html b/docs/acf-jda/co/aikar/commands/class-use/JDAConditionContext.html index 33f5860f..cfeae7c9 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDAConditionContext.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDAConditionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDAConditionContext (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDAConditionContext

              No usage of co.aikar.commands.JDAConditionContext
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDAListener.html b/docs/acf-jda/co/aikar/commands/class-use/JDAListener.html index 38159b54..e73c51eb 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDAListener.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDAListener.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDAListener (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDAListener

              No usage of co.aikar.commands.JDAListener
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDALocales.html b/docs/acf-jda/co/aikar/commands/class-use/JDALocales.html index 01288b85..9ba0ba3b 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDALocales.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDALocales.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDALocales (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDALocales

              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDAMessageFormatter.html b/docs/acf-jda/co/aikar/commands/class-use/JDAMessageFormatter.html index b858596b..acb7ae4b 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDAMessageFormatter.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDAMessageFormatter.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDAMessageFormatter (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDAMessageFormatter

              No usage of co.aikar.commands.JDAMessageFormatter
              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDAOptions.html b/docs/acf-jda/co/aikar/commands/class-use/JDAOptions.html index bff1b914..99eb4c63 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDAOptions.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDAOptions.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDAOptions (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDAOptions

              +
              + diff --git a/docs/acf-jda/co/aikar/commands/class-use/JDARootCommand.html b/docs/acf-jda/co/aikar/commands/class-use/JDARootCommand.html index b0b95fdf..020f44bb 100644 --- a/docs/acf-jda/co/aikar/commands/class-use/JDARootCommand.html +++ b/docs/acf-jda/co/aikar/commands/class-use/JDARootCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.JDARootCommand (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Uses of Class
              co.aikar.commands.JDARootCommand

              +
              + diff --git a/docs/acf-jda/co/aikar/commands/package-summary.html b/docs/acf-jda/co/aikar/commands/package-summary.html index d3a62931..fd8a9847 100644 --- a/docs/acf-jda/co/aikar/commands/package-summary.html +++ b/docs/acf-jda/co/aikar/commands/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Package co.aikar.commands

              +
              + diff --git a/docs/acf-jda/constant-values.html b/docs/acf-jda/constant-values.html index db79c15e..77dba868 100644 --- a/docs/acf-jda/constant-values.html +++ b/docs/acf-jda/constant-values.html @@ -1,12 +1,21 @@ - + - Constant Field Values (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Constant Field Values

              +

              Contents

              +
              +
              + diff --git a/docs/acf-jda/deprecated-list.html b/docs/acf-jda/deprecated-list.html index e8d2a438..4264f384 100644 --- a/docs/acf-jda/deprecated-list.html +++ b/docs/acf-jda/deprecated-list.html @@ -1,12 +1,21 @@ - + - Deprecated List (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Deprecated API

              Contents

              +
              + diff --git a/docs/acf-jda/element-list b/docs/acf-jda/element-list new file mode 100644 index 00000000..00803226 --- /dev/null +++ b/docs/acf-jda/element-list @@ -0,0 +1,2 @@ +co.aikar.commands +co.aikar.commands.annotation diff --git a/docs/acf-jda/index-all.html b/docs/acf-jda/index-all.html index 2f4ed496..ea5e1fc2 100644 --- a/docs/acf-jda/index-all.html +++ b/docs/acf-jda/index-all.html @@ -1,12 +1,21 @@ - + - Index (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +
              +
              A C D G H I J L O P R S U 
              All Classes All Packages

              A

              -
              addChild(BaseCommand) - Method in class co.aikar.commands.JDARootCommand
              +
              addChild(BaseCommand) - Method in class co.aikar.commands.JDARootCommand
               
              Author - Annotation Type in co.aikar.commands.annotation
              @@ -81,7 +105,7 @@ parsed from the user's input.
              - +

              C

              @@ -102,139 +126,139 @@
               
              completions - Variable in class co.aikar.commands.JDACommandManager
               
              -
              configProvider(CommandConfigProvider) - Method in class co.aikar.commands.JDAOptions
              +
              configProvider(CommandConfigProvider) - Method in class co.aikar.commands.JDAOptions
               
              contexts - Variable in class co.aikar.commands.JDACommandManager
               
              -
              create(JDA) - Method in class co.aikar.commands.JDAOptions
              +
              create(JDA) - Method in class co.aikar.commands.JDAOptions
               
              -
              createCommandContext(RegisteredCommand, CommandParameter, CommandIssuer, List<String>, int, Map<String, Object>) - Method in class co.aikar.commands.JDACommandManager
              +
              createCommandContext(RegisteredCommand, CommandParameter, CommandIssuer, List<String>, int, Map<String, Object>) - Method in class co.aikar.commands.JDACommandManager
               
              -
              createCompletionContext(RegisteredCommand, CommandIssuer, String, String, String[]) - Method in class co.aikar.commands.JDACommandManager
              +
              createCompletionContext(RegisteredCommand, CommandIssuer, String, String, String[]) - Method in class co.aikar.commands.JDACommandManager
               
              -
              createRootCommand(String) - Method in class co.aikar.commands.JDACommandManager
              +
              createRootCommand(String) - Method in class co.aikar.commands.JDACommandManager
               
              CrossGuild - Annotation Type in co.aikar.commands.annotation
              The CrossGuild annotation is to define whether the parameter should be guild-specific or global.
              - +

              D

              -
              defaultConfig(CommandConfig) - Method in class co.aikar.commands.JDAOptions
              +
              defaultConfig(CommandConfig) - Method in class co.aikar.commands.JDAOptions
               
              - +

              G

              -
              getBotOwnerId() - Method in class co.aikar.commands.JDACommandManager
              +
              getBotOwnerId() - Method in class co.aikar.commands.JDACommandManager
               
              -
              getChildren() - Method in class co.aikar.commands.JDARootCommand
              +
              getChildren() - Method in class co.aikar.commands.JDARootCommand
               
              -
              getCommandCompletions() - Method in class co.aikar.commands.JDACommandManager
              +
              getCommandCompletions() - Method in class co.aikar.commands.JDACommandManager
               
              -
              getCommandContexts() - Method in class co.aikar.commands.JDACommandManager
              +
              getCommandContexts() - Method in class co.aikar.commands.JDACommandManager
               
              -
              getCommandIssuer(Object) - Method in class co.aikar.commands.JDACommandManager
              +
              getCommandIssuer(Object) - Method in class co.aikar.commands.JDACommandManager
               
              -
              getCommandName() - Method in class co.aikar.commands.JDARootCommand
              +
              getCommandName() - Method in class co.aikar.commands.JDARootCommand
               
              -
              getCommandPrefix(CommandIssuer) - Method in class co.aikar.commands.JDACommandManager
              +
              getCommandPrefix(CommandIssuer) - Method in class co.aikar.commands.JDACommandManager
               
              -
              getCommandPrefixes() - Method in interface co.aikar.commands.CommandConfig
              +
              getCommandPrefixes() - Method in interface co.aikar.commands.CommandConfig
               
              -
              getCommandPrefixes() - Method in class co.aikar.commands.JDACommandConfig
              +
              getCommandPrefixes() - Method in class co.aikar.commands.JDACommandConfig
               
              -
              getConfigProvider() - Method in class co.aikar.commands.JDACommandManager
              +
              getConfigProvider() - Method in class co.aikar.commands.JDACommandManager
               
              -
              getDefaultConfig() - Method in class co.aikar.commands.JDACommandManager
              +
              getDefaultConfig() - Method in class co.aikar.commands.JDACommandManager
               
              -
              getDefCommand() - Method in class co.aikar.commands.JDARootCommand
              +
              getDefCommand() - Method in class co.aikar.commands.JDARootCommand
               
              -
              getEvent() - Method in class co.aikar.commands.JDACommandEvent
              +
              getEvent() - Method in class co.aikar.commands.JDACommandEvent
               
              -
              getIssuer() - Method in class co.aikar.commands.JDACommandEvent
              +
              getIssuer() - Method in class co.aikar.commands.JDACommandEvent
               
              -
              getJDA() - Method in class co.aikar.commands.JDACommandManager
              +
              getJDA() - Method in class co.aikar.commands.JDACommandManager
               
              -
              getLocales() - Method in class co.aikar.commands.JDACommandManager
              +
              getLocales() - Method in class co.aikar.commands.JDACommandManager
               
              -
              getLogger() - Method in class co.aikar.commands.JDACommandManager
              +
              getLogger() - Method in class co.aikar.commands.JDACommandManager
               
              -
              getManager() - Method in class co.aikar.commands.JDACommandEvent
              +
              getManager() - Method in class co.aikar.commands.JDACommandEvent
               
              -
              getManager() - Method in class co.aikar.commands.JDARootCommand
              +
              getManager() - Method in class co.aikar.commands.JDARootCommand
               
              -
              getPermissionResolver() - Method in class co.aikar.commands.JDACommandManager
              +
              getPermissionResolver() - Method in class co.aikar.commands.JDACommandManager
               
              -
              getRegisteredRootCommands() - Method in class co.aikar.commands.JDACommandManager
              +
              getRegisteredRootCommands() - Method in class co.aikar.commands.JDACommandManager
               
              -
              getSubCommands() - Method in class co.aikar.commands.JDARootCommand
              +
              getSubCommands() - Method in class co.aikar.commands.JDARootCommand
               
              -
              getUniqueId() - Method in class co.aikar.commands.JDACommandEvent
              +
              getUniqueId() - Method in class co.aikar.commands.JDACommandEvent
               
              - +

              H

              -
              hasPermission(JDACommandManager, JDACommandEvent, String) - Method in interface co.aikar.commands.CommandPermissionResolver
              +
              hasPermission(JDACommandManager, JDACommandEvent, String) - Method in interface co.aikar.commands.CommandPermissionResolver
               
              -
              hasPermission(String) - Method in class co.aikar.commands.JDACommandEvent
              +
              hasPermission(JDACommandManager, JDACommandEvent, String) - Method in class co.aikar.commands.JDACommandPermissionResolver
               
              -
              hasPermission(JDACommandManager, JDACommandEvent, String) - Method in class co.aikar.commands.JDACommandPermissionResolver
              +
              hasPermission(String) - Method in class co.aikar.commands.JDACommandEvent
               
              -
              hasRegisteredCommands() - Method in class co.aikar.commands.JDACommandManager
              +
              hasRegisteredCommands() - Method in class co.aikar.commands.JDACommandManager
               
              - +

              I

              -
              isCommandIssuer(Class<?>) - Method in class co.aikar.commands.JDACommandManager
              +
              isCommandIssuer(Class<?>) - Method in class co.aikar.commands.JDACommandManager
               
              -
              isPlayer() - Method in class co.aikar.commands.JDACommandEvent
              +
              isPlayer() - Method in class co.aikar.commands.JDACommandEvent
               
              - +

              J

              JDACommandCompletions - Class in co.aikar.commands
               
              -
              JDACommandCompletions(CommandManager) - Constructor for class co.aikar.commands.JDACommandCompletions
              +
              JDACommandCompletions(CommandManager) - Constructor for class co.aikar.commands.JDACommandCompletions
               
              JDACommandConfig - Class in co.aikar.commands
               
              -
              JDACommandConfig() - Constructor for class co.aikar.commands.JDACommandConfig
              +
              JDACommandConfig() - Constructor for class co.aikar.commands.JDACommandConfig
               
              JDACommandContexts - Class in co.aikar.commands
               
              -
              JDACommandContexts(JDACommandManager) - Constructor for class co.aikar.commands.JDACommandContexts
              +
              JDACommandContexts(JDACommandManager) - Constructor for class co.aikar.commands.JDACommandContexts
               
              JDACommandEvent - Class in co.aikar.commands
               
              -
              JDACommandEvent(JDACommandManager, MessageReceivedEvent) - Constructor for class co.aikar.commands.JDACommandEvent
              +
              JDACommandEvent(JDACommandManager, MessageReceivedEvent) - Constructor for class co.aikar.commands.JDACommandEvent
               
              JDACommandExecutionContext - Class in co.aikar.commands
               
              JDACommandManager - Class in co.aikar.commands
               
              -
              JDACommandManager(JDA) - Constructor for class co.aikar.commands.JDACommandManager
              +
              JDACommandManager(JDA) - Constructor for class co.aikar.commands.JDACommandManager
               
              -
              JDACommandManager(JDA, JDAOptions) - Constructor for class co.aikar.commands.JDACommandManager
              +
              JDACommandManager(JDA, JDAOptions) - Constructor for class co.aikar.commands.JDACommandManager
               
              JDACommandPermissionResolver - Class in co.aikar.commands
               
              -
              JDACommandPermissionResolver() - Constructor for class co.aikar.commands.JDACommandPermissionResolver
              +
              JDACommandPermissionResolver() - Constructor for class co.aikar.commands.JDACommandPermissionResolver
               
              JDAConditionContext - Class in co.aikar.commands
               
              @@ -242,66 +266,66 @@
               
              JDALocales - Class in co.aikar.commands
               
              -
              JDALocales(CommandManager) - Constructor for class co.aikar.commands.JDALocales
              +
              JDALocales(CommandManager) - Constructor for class co.aikar.commands.JDALocales
               
              JDAMessageFormatter - Class in co.aikar.commands
               
              -
              JDAMessageFormatter() - Constructor for class co.aikar.commands.JDAMessageFormatter
              +
              JDAMessageFormatter() - Constructor for class co.aikar.commands.JDAMessageFormatter
               
              JDAOptions - Class in co.aikar.commands
               
              -
              JDAOptions() - Constructor for class co.aikar.commands.JDAOptions
              +
              JDAOptions() - Constructor for class co.aikar.commands.JDAOptions
               
              JDARootCommand - Class in co.aikar.commands
               
              - +

              L

              locales - Variable in class co.aikar.commands.JDACommandManager
               
              -
              log(LogLevel, String, Throwable) - Method in class co.aikar.commands.JDACommandManager
              +
              log(LogLevel, String, Throwable) - Method in class co.aikar.commands.JDACommandManager
               
              - +

              O

              -
              onMessageReceived(MessageReceivedEvent) - Method in class co.aikar.commands.JDAListener
              +
              onMessageReceived(MessageReceivedEvent) - Method in class co.aikar.commands.JDAListener
               
              -
              onReady(ReadyEvent) - Method in class co.aikar.commands.JDAListener
              +
              onReady(ReadyEvent) - Method in class co.aikar.commands.JDAListener
               
              -
              options() - Static method in class co.aikar.commands.JDACommandManager
              +
              options() - Static method in class co.aikar.commands.JDACommandManager
               
              - +

              P

              -
              permissionResolver(CommandPermissionResolver) - Method in class co.aikar.commands.JDAOptions
              +
              permissionResolver(CommandPermissionResolver) - Method in class co.aikar.commands.JDAOptions
               
              -
              provide(MessageReceivedEvent) - Method in interface co.aikar.commands.CommandConfig
              +
              provide(MessageReceivedEvent) - Method in interface co.aikar.commands.CommandConfig
               
              -
              provide(MessageReceivedEvent) - Method in interface co.aikar.commands.CommandConfigProvider
              +
              provide(MessageReceivedEvent) - Method in interface co.aikar.commands.CommandConfigProvider
               
              - +

              R

              -
              registerAsyncCompletion(String, CommandCompletions.AsyncCommandCompletionHandler<CommandCompletionContext<?>>) - Method in class co.aikar.commands.JDACommandCompletions
              +
              registerAsyncCompletion(String, CommandCompletions.AsyncCommandCompletionHandler<CommandCompletionContext<?>>) - Method in class co.aikar.commands.JDACommandCompletions
               
              -
              registerCommand(BaseCommand) - Method in class co.aikar.commands.JDACommandManager
              +
              registerCommand(BaseCommand) - Method in class co.aikar.commands.JDACommandManager
               
              -
              registerCompletion(String, CommandCompletions.CommandCompletionHandler<CommandCompletionContext<?>>) - Method in class co.aikar.commands.JDACommandCompletions
              +
              registerCompletion(String, CommandCompletions.CommandCompletionHandler<CommandCompletionContext<?>>) - Method in class co.aikar.commands.JDACommandCompletions
               
              - +

              S

              @@ -311,40 +335,43 @@
              The SelfUser annotation is to define whether the parameter should be represented by JDA's user object or if it should be parsed from command input.
              -
              sendMessage(Message) - Method in class co.aikar.commands.JDACommandEvent
              +
              sendMessage(Message) - Method in class co.aikar.commands.JDACommandEvent
               
              -
              sendMessage(MessageEmbed) - Method in class co.aikar.commands.JDACommandEvent
              +
              sendMessage(MessageEmbed) - Method in class co.aikar.commands.JDACommandEvent
               
              -
              sendMessageInternal(String) - Method in class co.aikar.commands.JDACommandEvent
              +
              sendMessageInternal(String) - Method in class co.aikar.commands.JDACommandEvent
               
              -
              setConfigProvider(CommandConfigProvider) - Method in class co.aikar.commands.JDACommandManager
              +
              setConfigProvider(CommandConfigProvider) - Method in class co.aikar.commands.JDACommandManager
               
              -
              setDefaultConfig(CommandConfig) - Method in class co.aikar.commands.JDACommandManager
              +
              setDefaultConfig(CommandConfig) - Method in class co.aikar.commands.JDACommandManager
               
              -
              setLogger(Logger) - Method in class co.aikar.commands.JDACommandManager
              +
              setLogger(Logger) - Method in class co.aikar.commands.JDACommandManager
               
              -
              setPermissionResolver(CommandPermissionResolver) - Method in class co.aikar.commands.JDACommandManager
              +
              setPermissionResolver(CommandPermissionResolver) - Method in class co.aikar.commands.JDACommandManager
               
              - +

              U

              -
              unregisterCommand(BaseCommand) - Method in class co.aikar.commands.JDACommandManager
              +
              unregisterCommand(BaseCommand) - Method in class co.aikar.commands.JDACommandManager
               
              -A C D G H I J L O P R S U  +A C D G H I J L O P R S U 
              All Classes All Packages +
              + diff --git a/docs/acf-jda/index.html b/docs/acf-jda/index.html index f1a419c6..9155288a 100644 --- a/docs/acf-jda/index.html +++ b/docs/acf-jda/index.html @@ -1,76 +1,165 @@ - + +Overview (ACF (JDA) 0.5.0-SNAPSHOT API) -ACF (JDA) 0.5.0-SNAPSHOT API - + + + + + + + + + - - - - - - - +<body> +<script type="text/javascript"><!-- + try { + if (location.href.indexOf('is-external=true') == -1) { + parent.document.title="Overview (ACF (JDA) 0.5.0-SNAPSHOT API)"; + } + } + catch(err) { + } +//--> +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script');</script> <noscript> <div>JavaScript is disabled on your browser.</div> </noscript> -<h2>Frame Alert</h2> -<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p> - - +
              + +
              +
              +

              ACF (JDA) 0.5.0-SNAPSHOT API

              +
              +
              +
              + + + + + + + + + + + + + + + + +
              Packages 
              PackageDescription
              co.aikar.commands 
              co.aikar.commands.annotation 
              +
              +
              +
              + +

              Copyright © 2020. All rights reserved.

              +
              + diff --git a/docs/acf-jda/jquery/external/jquery/jquery.js b/docs/acf-jda/jquery/external/jquery/jquery.js new file mode 100644 index 00000000..9b5206bc --- /dev/null +++ b/docs/acf-jda/jquery/external/jquery/jquery.js @@ -0,0 +1,10364 @@ +/*! + * jQuery JavaScript Library v3.3.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2018-01-20T17:24Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + + + + var preservedScriptAttributes = { + type: true, + src: true, + noModule: true + }; + + function DOMEval( code, doc, node ) { + doc = doc || document; + + var i, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + if ( node[ i ] ) { + script[ i ] = node[ i ]; + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.3.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && Array.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( nodeName( elem, "iframe" ) ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting
              ", "
              " ], + col: [ 2, "", "
              " ], + tr: [ 2, "", "
              " ], + td: [ 3, "", "
              " ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + div.style.position = "absolute"; + scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a property mapped along what jQuery.cssProps suggests or to +// a vendor prefixed property. +function finalPropName( name ) { + var ret = jQuery.cssProps[ name ]; + if ( !ret ) { + ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + } + return ret; +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + ) ); + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + val = curCSS( elem, dimension, styles ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox; + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = valueIsBorderBox && + ( support.boxSizingReliable() || val === elem.style[ dimension ] ); + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + if ( val === "auto" || + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { + + val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; + + // offsetWidth/offsetHeight provide border-box values + valueIsBorderBox = true; + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra && boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ); + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && support.scrollboxSize() === styles.position ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = Date.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "\r\n"; + +// inject VBScript +document.write(IEBinaryToArray_ByteStr_Script); + +global.JSZipUtils._getBinaryFromXHR = function (xhr) { + var binary = xhr.responseBody; + var byteMapping = {}; + for ( var i = 0; i < 256; i++ ) { + for ( var j = 0; j < 256; j++ ) { + byteMapping[ String.fromCharCode( i + (j << 8) ) ] = + String.fromCharCode(i) + String.fromCharCode(j); + } + } + var rawBytes = IEBinaryToArray_ByteStr(binary); + var lastChr = IEBinaryToArray_ByteStr_Last(binary); + return rawBytes.replace(/[\s\S]/g, function( match ) { + return byteMapping[match]; + }) + lastChr; +}; + +// enforcing Stuk's coding style +// vim: set shiftwidth=4 softtabstop=4: + +},{}]},{},[1]) +; diff --git a/docs/acf-jda/jquery/jszip-utils/dist/jszip-utils-ie.min.js b/docs/acf-jda/jquery/jszip-utils/dist/jszip-utils-ie.min.js new file mode 100644 index 00000000..93d8bc8e --- /dev/null +++ b/docs/acf-jda/jquery/jszip-utils/dist/jszip-utils-ie.min.js @@ -0,0 +1,10 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); diff --git a/docs/acf-jda/jquery/jszip-utils/dist/jszip-utils.js b/docs/acf-jda/jquery/jszip-utils/dist/jszip-utils.js new file mode 100644 index 00000000..775895ec --- /dev/null +++ b/docs/acf-jda/jquery/jszip-utils/dist/jszip-utils.js @@ -0,0 +1,118 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ + +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64; + enc4 = remainingBytes > 2 ? (chr3 & 63) : 64; + + output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4)); + + } + + return output.join(""); +}; + +// public method for decoding +exports.decode = function(input) { + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0, resultIndex = 0; + + var dataUrlPrefix = "data:"; + + if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) { + // This is a common error: people give a data url + // (data:image/png;base64,iVBOR...) with a {base64: true} and + // wonders why things don't work. + // We can detect that the string input looks like a data url but we + // *can't* be sure it is one: removing everything up to the comma would + // be too dangerous. + throw new Error("Invalid base64 input, it looks like a data url."); + } + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + var totalLength = input.length * 3 / 4; + if(input.charAt(input.length - 1) === _keyStr.charAt(64)) { + totalLength--; + } + if(input.charAt(input.length - 2) === _keyStr.charAt(64)) { + totalLength--; + } + if (totalLength % 1 !== 0) { + // totalLength is not an integer, the length does not match a valid + // base64 content. That can happen if: + // - the input is not a base64 content + // - the input is *almost* a base64 content, with a extra chars at the + // beginning or at the end + // - the input uses a base64 variant (base64url for example) + throw new Error("Invalid base64 input, bad content length."); + } + var output; + if (support.uint8array) { + output = new Uint8Array(totalLength|0); + } else { + output = new Array(totalLength|0); + } + + while (i < input.length) { + + enc1 = _keyStr.indexOf(input.charAt(i++)); + enc2 = _keyStr.indexOf(input.charAt(i++)); + enc3 = _keyStr.indexOf(input.charAt(i++)); + enc4 = _keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output[resultIndex++] = chr1; + + if (enc3 !== 64) { + output[resultIndex++] = chr2; + } + if (enc4 !== 64) { + output[resultIndex++] = chr3; + } + + } + + return output; +}; + +},{"./support":30,"./utils":32}],2:[function(require,module,exports){ +'use strict'; + +var external = require("./external"); +var DataWorker = require('./stream/DataWorker'); +var DataLengthProbe = require('./stream/DataLengthProbe'); +var Crc32Probe = require('./stream/Crc32Probe'); +var DataLengthProbe = require('./stream/DataLengthProbe'); + +/** + * Represent a compressed object, with everything needed to decompress it. + * @constructor + * @param {number} compressedSize the size of the data compressed. + * @param {number} uncompressedSize the size of the data after decompression. + * @param {number} crc32 the crc32 of the decompressed file. + * @param {object} compression the type of compression, see lib/compressions.js. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data. + */ +function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) { + this.compressedSize = compressedSize; + this.uncompressedSize = uncompressedSize; + this.crc32 = crc32; + this.compression = compression; + this.compressedContent = data; +} + +CompressedObject.prototype = { + /** + * Create a worker to get the uncompressed content. + * @return {GenericWorker} the worker. + */ + getContentWorker : function () { + var worker = new DataWorker(external.Promise.resolve(this.compressedContent)) + .pipe(this.compression.uncompressWorker()) + .pipe(new DataLengthProbe("data_length")); + + var that = this; + worker.on("end", function () { + if(this.streamInfo['data_length'] !== that.uncompressedSize) { + throw new Error("Bug : uncompressed data size mismatch"); + } + }); + return worker; + }, + /** + * Create a worker to get the compressed content. + * @return {GenericWorker} the worker. + */ + getCompressedWorker : function () { + return new DataWorker(external.Promise.resolve(this.compressedContent)) + .withStreamInfo("compressedSize", this.compressedSize) + .withStreamInfo("uncompressedSize", this.uncompressedSize) + .withStreamInfo("crc32", this.crc32) + .withStreamInfo("compression", this.compression) + ; + } +}; + +/** + * Chain the given worker with other workers to compress the content with the + * given compresion. + * @param {GenericWorker} uncompressedWorker the worker to pipe. + * @param {Object} compression the compression object. + * @param {Object} compressionOptions the options to use when compressing. + * @return {GenericWorker} the new worker compressing the content. + */ +CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions) { + return uncompressedWorker + .pipe(new Crc32Probe()) + .pipe(new DataLengthProbe("uncompressedSize")) + .pipe(compression.compressWorker(compressionOptions)) + .pipe(new DataLengthProbe("compressedSize")) + .withStreamInfo("compression", compression); +}; + +module.exports = CompressedObject; + +},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require("./stream/GenericWorker"); + +exports.STORE = { + magic: "\x00\x00", + compressWorker : function (compressionOptions) { + return new GenericWorker("STORE compression"); + }, + uncompressWorker : function () { + return new GenericWorker("STORE decompression"); + } +}; +exports.DEFLATE = require('./flate'); + +},{"./flate":7,"./stream/GenericWorker":28}],4:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); + +/** + * The following functions come from pako, from pako/lib/zlib/crc32.js + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +// That's all for the pako functions. + +/** + * Compute the crc32 of a string. + * This is almost the same as the function crc32, but for strings. Using the + * same function for the two use cases leads to horrible performances. + * @param {Number} crc the starting value of the crc. + * @param {String} str the string to use. + * @param {Number} len the length of the string. + * @param {Number} pos the starting position for the crc32 computation. + * @return {Number} the computed crc32. + */ +function crc32str(crc, str, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +module.exports = function crc32wrapper(input, crc) { + if (typeof input === "undefined" || !input.length) { + return 0; + } + + var isArray = utils.getTypeOf(input) !== "string"; + + if(isArray) { + return crc32(crc|0, input, input.length, 0); + } else { + return crc32str(crc|0, input, input.length, 0); + } +}; + +},{"./utils":32}],5:[function(require,module,exports){ +'use strict'; +exports.base64 = false; +exports.binary = false; +exports.dir = false; +exports.createFolders = true; +exports.date = null; +exports.compression = null; +exports.compressionOptions = null; +exports.comment = null; +exports.unixPermissions = null; +exports.dosPermissions = null; + +},{}],6:[function(require,module,exports){ +/* global Promise */ +'use strict'; + +// load the global object first: +// - it should be better integrated in the system (unhandledRejection in node) +// - the environment may have a custom Promise implementation (see zone.js) +var ES6Promise = null; +if (typeof Promise !== "undefined") { + ES6Promise = Promise; +} else { + ES6Promise = require("lie"); +} + +/** + * Let the user use/change some implementations. + */ +module.exports = { + Promise: ES6Promise +}; + +},{"lie":58}],7:[function(require,module,exports){ +'use strict'; +var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); + +var pako = require("pako"); +var utils = require("./utils"); +var GenericWorker = require("./stream/GenericWorker"); + +var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array"; + +exports.magic = "\x08\x00"; + +/** + * Create a worker that uses pako to inflate/deflate. + * @constructor + * @param {String} action the name of the pako function to call : either "Deflate" or "Inflate". + * @param {Object} options the options to use when (de)compressing. + */ +function FlateWorker(action, options) { + GenericWorker.call(this, "FlateWorker/" + action); + + this._pako = null; + this._pakoAction = action; + this._pakoOptions = options; + // the `meta` object from the last chunk received + // this allow this worker to pass around metadata + this.meta = {}; +} + +utils.inherits(FlateWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +FlateWorker.prototype.processChunk = function (chunk) { + this.meta = chunk.meta; + if (this._pako === null) { + this._createPako(); + } + this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false); +}; + +/** + * @see GenericWorker.flush + */ +FlateWorker.prototype.flush = function () { + GenericWorker.prototype.flush.call(this); + if (this._pako === null) { + this._createPako(); + } + this._pako.push([], true); +}; +/** + * @see GenericWorker.cleanUp + */ +FlateWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this._pako = null; +}; + +/** + * Create the _pako object. + * TODO: lazy-loading this object isn't the best solution but it's the + * quickest. The best solution is to lazy-load the worker list. See also the + * issue #446. + */ +FlateWorker.prototype._createPako = function () { + this._pako = new pako[this._pakoAction]({ + raw: true, + level: this._pakoOptions.level || -1 // default compression + }); + var self = this; + this._pako.onData = function(data) { + self.push({ + data : data, + meta : self.meta + }); + }; +}; + +exports.compressWorker = function (compressionOptions) { + return new FlateWorker("Deflate", compressionOptions); +}; +exports.uncompressWorker = function () { + return new FlateWorker("Inflate", {}); +}; + +},{"./stream/GenericWorker":28,"./utils":32,"pako":59}],8:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); +var utf8 = require('../utf8'); +var crc32 = require('../crc32'); +var signature = require('../signature'); + +/** + * Transform an integer into a string in hexadecimal. + * @private + * @param {number} dec the number to convert. + * @param {number} bytes the number of bytes to generate. + * @returns {string} the result. + */ +var decToHex = function(dec, bytes) { + var hex = "", i; + for (i = 0; i < bytes; i++) { + hex += String.fromCharCode(dec & 0xff); + dec = dec >>> 8; + } + return hex; +}; + +/** + * Generate the UNIX part of the external file attributes. + * @param {Object} unixPermissions the unix permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : + * + * TTTTsstrwxrwxrwx0000000000ADVSHR + * ^^^^____________________________ file type, see zipinfo.c (UNX_*) + * ^^^_________________________ setuid, setgid, sticky + * ^^^^^^^^^________________ permissions + * ^^^^^^^^^^______ not used ? + * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only + */ +var generateUnixExternalFileAttr = function (unixPermissions, isDir) { + + var result = unixPermissions; + if (!unixPermissions) { + // I can't use octal values in strict mode, hence the hexa. + // 040775 => 0x41fd + // 0100664 => 0x81b4 + result = isDir ? 0x41fd : 0x81b4; + } + return (result & 0xFFFF) << 16; +}; + +/** + * Generate the DOS part of the external file attributes. + * @param {Object} dosPermissions the dos permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * Bit 0 Read-Only + * Bit 1 Hidden + * Bit 2 System + * Bit 3 Volume Label + * Bit 4 Directory + * Bit 5 Archive + */ +var generateDosExternalFileAttr = function (dosPermissions, isDir) { + + // the dir flag is already set for compatibility + return (dosPermissions || 0) & 0x3F; +}; + +/** + * Generate the various parts used in the construction of the final zip file. + * @param {Object} streamInfo the hash with informations about the compressed file. + * @param {Boolean} streamedContent is the content streamed ? + * @param {Boolean} streamingEnded is the stream finished ? + * @param {number} offset the current offset from the start of the zip file. + * @param {String} platform let's pretend we are this platform (change platform dependents fields) + * @param {Function} encodeFileName the function to encode the file name / comment. + * @return {Object} the zip parts. + */ +var generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) { + var file = streamInfo['file'], + compression = streamInfo['compression'], + useCustomEncoding = encodeFileName !== utf8.utf8encode, + encodedFileName = utils.transformTo("string", encodeFileName(file.name)), + utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), + comment = file.comment, + encodedComment = utils.transformTo("string", encodeFileName(comment)), + utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), + useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, + useUTF8ForComment = utfEncodedComment.length !== comment.length, + dosTime, + dosDate, + extraFields = "", + unicodePathExtraField = "", + unicodeCommentExtraField = "", + dir = file.dir, + date = file.date; + + + var dataInfo = { + crc32 : 0, + compressedSize : 0, + uncompressedSize : 0 + }; + + // if the content is streamed, the sizes/crc32 are only available AFTER + // the end of the stream. + if (!streamedContent || streamingEnded) { + dataInfo.crc32 = streamInfo['crc32']; + dataInfo.compressedSize = streamInfo['compressedSize']; + dataInfo.uncompressedSize = streamInfo['uncompressedSize']; + } + + var bitflag = 0; + if (streamedContent) { + // Bit 3: the sizes/crc32 are set to zero in the local header. + // The correct values are put in the data descriptor immediately + // following the compressed data. + bitflag |= 0x0008; + } + if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) { + // Bit 11: Language encoding flag (EFS). + bitflag |= 0x0800; + } + + + var extFileAttr = 0; + var versionMadeBy = 0; + if (dir) { + // dos or unix, we set the dos dir flag + extFileAttr |= 0x00010; + } + if(platform === "UNIX") { + versionMadeBy = 0x031E; // UNIX, version 3.0 + extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); + } else { // DOS or other, fallback to DOS + versionMadeBy = 0x0014; // DOS, version 2.0 + extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); + } + + // date + // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html + + dosTime = date.getUTCHours(); + dosTime = dosTime << 6; + dosTime = dosTime | date.getUTCMinutes(); + dosTime = dosTime << 5; + dosTime = dosTime | date.getUTCSeconds() / 2; + + dosDate = date.getUTCFullYear() - 1980; + dosDate = dosDate << 4; + dosDate = dosDate | (date.getUTCMonth() + 1); + dosDate = dosDate << 5; + dosDate = dosDate | date.getUTCDate(); + + if (useUTF8ForFileName) { + // set the unicode path extra field. unzip needs at least one extra + // field to correctly handle unicode path, so using the path is as good + // as any other information. This could improve the situation with + // other archive managers too. + // This field is usually used without the utf8 flag, with a non + // unicode path in the header (winrar, winzip). This helps (a bit) + // with the messy Windows' default compressed folders feature but + // breaks on p7zip which doesn't seek the unicode path extra field. + // So for now, UTF-8 everywhere ! + unicodePathExtraField = + // Version + decToHex(1, 1) + + // NameCRC32 + decToHex(crc32(encodedFileName), 4) + + // UnicodeName + utfEncodedFileName; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x70" + + // size + decToHex(unicodePathExtraField.length, 2) + + // content + unicodePathExtraField; + } + + if(useUTF8ForComment) { + + unicodeCommentExtraField = + // Version + decToHex(1, 1) + + // CommentCRC32 + decToHex(crc32(encodedComment), 4) + + // UnicodeName + utfEncodedComment; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x63" + + // size + decToHex(unicodeCommentExtraField.length, 2) + + // content + unicodeCommentExtraField; + } + + var header = ""; + + // version needed to extract + header += "\x0A\x00"; + // general purpose bit flag + header += decToHex(bitflag, 2); + // compression method + header += compression.magic; + // last mod file time + header += decToHex(dosTime, 2); + // last mod file date + header += decToHex(dosDate, 2); + // crc-32 + header += decToHex(dataInfo.crc32, 4); + // compressed size + header += decToHex(dataInfo.compressedSize, 4); + // uncompressed size + header += decToHex(dataInfo.uncompressedSize, 4); + // file name length + header += decToHex(encodedFileName.length, 2); + // extra field length + header += decToHex(extraFields.length, 2); + + + var fileRecord = signature.LOCAL_FILE_HEADER + header + encodedFileName + extraFields; + + var dirRecord = signature.CENTRAL_FILE_HEADER + + // version made by (00: DOS) + decToHex(versionMadeBy, 2) + + // file header (common to file and central directory) + header + + // file comment length + decToHex(encodedComment.length, 2) + + // disk number start + "\x00\x00" + + // internal file attributes TODO + "\x00\x00" + + // external file attributes + decToHex(extFileAttr, 4) + + // relative offset of local header + decToHex(offset, 4) + + // file name + encodedFileName + + // extra field + extraFields + + // file comment + encodedComment; + + return { + fileRecord: fileRecord, + dirRecord: dirRecord + }; +}; + +/** + * Generate the EOCD record. + * @param {Number} entriesCount the number of entries in the zip file. + * @param {Number} centralDirLength the length (in bytes) of the central dir. + * @param {Number} localDirLength the length (in bytes) of the local dir. + * @param {String} comment the zip file comment as a binary string. + * @param {Function} encodeFileName the function to encode the comment. + * @return {String} the EOCD record. + */ +var generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) { + var dirEnd = ""; + var encodedComment = utils.transformTo("string", encodeFileName(comment)); + + // end of central dir signature + dirEnd = signature.CENTRAL_DIRECTORY_END + + // number of this disk + "\x00\x00" + + // number of the disk with the start of the central directory + "\x00\x00" + + // total number of entries in the central directory on this disk + decToHex(entriesCount, 2) + + // total number of entries in the central directory + decToHex(entriesCount, 2) + + // size of the central directory 4 bytes + decToHex(centralDirLength, 4) + + // offset of start of central directory with respect to the starting disk number + decToHex(localDirLength, 4) + + // .ZIP file comment length + decToHex(encodedComment.length, 2) + + // .ZIP file comment + encodedComment; + + return dirEnd; +}; + +/** + * Generate data descriptors for a file entry. + * @param {Object} streamInfo the hash generated by a worker, containing informations + * on the file entry. + * @return {String} the data descriptors. + */ +var generateDataDescriptors = function (streamInfo) { + var descriptor = ""; + descriptor = signature.DATA_DESCRIPTOR + + // crc-32 4 bytes + decToHex(streamInfo['crc32'], 4) + + // compressed size 4 bytes + decToHex(streamInfo['compressedSize'], 4) + + // uncompressed size 4 bytes + decToHex(streamInfo['uncompressedSize'], 4); + + return descriptor; +}; + + +/** + * A worker to concatenate other workers to create a zip file. + * @param {Boolean} streamFiles `true` to stream the content of the files, + * `false` to accumulate it. + * @param {String} comment the comment to use. + * @param {String} platform the platform to use, "UNIX" or "DOS". + * @param {Function} encodeFileName the function to encode file names and comments. + */ +function ZipFileWorker(streamFiles, comment, platform, encodeFileName) { + GenericWorker.call(this, "ZipFileWorker"); + // The number of bytes written so far. This doesn't count accumulated chunks. + this.bytesWritten = 0; + // The comment of the zip file + this.zipComment = comment; + // The platform "generating" the zip file. + this.zipPlatform = platform; + // the function to encode file names and comments. + this.encodeFileName = encodeFileName; + // Should we stream the content of the files ? + this.streamFiles = streamFiles; + // If `streamFiles` is false, we will need to accumulate the content of the + // files to calculate sizes / crc32 (and write them *before* the content). + // This boolean indicates if we are accumulating chunks (it will change a lot + // during the lifetime of this worker). + this.accumulate = false; + // The buffer receiving chunks when accumulating content. + this.contentBuffer = []; + // The list of generated directory records. + this.dirRecords = []; + // The offset (in bytes) from the beginning of the zip file for the current source. + this.currentSourceOffset = 0; + // The total number of entries in this zip file. + this.entriesCount = 0; + // the name of the file currently being added, null when handling the end of the zip file. + // Used for the emited metadata. + this.currentFile = null; + + + + this._sources = []; +} +utils.inherits(ZipFileWorker, GenericWorker); + +/** + * @see GenericWorker.push + */ +ZipFileWorker.prototype.push = function (chunk) { + + var currentFilePercent = chunk.meta.percent || 0; + var entriesCount = this.entriesCount; + var remainingFiles = this._sources.length; + + if(this.accumulate) { + this.contentBuffer.push(chunk); + } else { + this.bytesWritten += chunk.data.length; + + GenericWorker.prototype.push.call(this, { + data : chunk.data, + meta : { + currentFile : this.currentFile, + percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100 + } + }); + } +}; + +/** + * The worker started a new source (an other worker). + * @param {Object} streamInfo the streamInfo object from the new source. + */ +ZipFileWorker.prototype.openedSource = function (streamInfo) { + this.currentSourceOffset = this.bytesWritten; + this.currentFile = streamInfo['file'].name; + + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + + // don't stream folders (because they don't have any content) + if(streamedContent) { + var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + } else { + // we need to wait for the whole file before pushing anything + this.accumulate = true; + } +}; + +/** + * The worker finished a source (an other worker). + * @param {Object} streamInfo the streamInfo object from the finished source. + */ +ZipFileWorker.prototype.closedSource = function (streamInfo) { + this.accumulate = false; + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + + this.dirRecords.push(record.dirRecord); + if(streamedContent) { + // after the streamed file, we put data descriptors + this.push({ + data : generateDataDescriptors(streamInfo), + meta : {percent:100} + }); + } else { + // the content wasn't streamed, we need to push everything now + // first the file record, then the content + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + while(this.contentBuffer.length) { + this.push(this.contentBuffer.shift()); + } + } + this.currentFile = null; +}; + +/** + * @see GenericWorker.flush + */ +ZipFileWorker.prototype.flush = function () { + + var localDirLength = this.bytesWritten; + for(var i = 0; i < this.dirRecords.length; i++) { + this.push({ + data : this.dirRecords[i], + meta : {percent:100} + }); + } + var centralDirLength = this.bytesWritten - localDirLength; + + var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName); + + this.push({ + data : dirEnd, + meta : {percent:100} + }); +}; + +/** + * Prepare the next source to be read. + */ +ZipFileWorker.prototype.prepareNextSource = function () { + this.previous = this._sources.shift(); + this.openedSource(this.previous.streamInfo); + if (this.isPaused) { + this.previous.pause(); + } else { + this.previous.resume(); + } +}; + +/** + * @see GenericWorker.registerPrevious + */ +ZipFileWorker.prototype.registerPrevious = function (previous) { + this._sources.push(previous); + var self = this; + + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.closedSource(self.previous.streamInfo); + if(self._sources.length) { + self.prepareNextSource(); + } else { + self.end(); + } + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; +}; + +/** + * @see GenericWorker.resume + */ +ZipFileWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this.previous && this._sources.length) { + this.prepareNextSource(); + return true; + } + if (!this.previous && !this._sources.length && !this.generatedError) { + this.end(); + return true; + } +}; + +/** + * @see GenericWorker.error + */ +ZipFileWorker.prototype.error = function (e) { + var sources = this._sources; + if(!GenericWorker.prototype.error.call(this, e)) { + return false; + } + for(var i = 0; i < sources.length; i++) { + try { + sources[i].error(e); + } catch(e) { + // the `error` exploded, nothing to do + } + } + return true; +}; + +/** + * @see GenericWorker.lock + */ +ZipFileWorker.prototype.lock = function () { + GenericWorker.prototype.lock.call(this); + var sources = this._sources; + for(var i = 0; i < sources.length; i++) { + sources[i].lock(); + } +}; + +module.exports = ZipFileWorker; + +},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(require,module,exports){ +'use strict'; + +var compressions = require('../compressions'); +var ZipFileWorker = require('./ZipFileWorker'); + +/** + * Find the compression to use. + * @param {String} fileCompression the compression defined at the file level, if any. + * @param {String} zipCompression the compression defined at the load() level. + * @return {Object} the compression object to use. + */ +var getCompression = function (fileCompression, zipCompression) { + + var compressionName = fileCompression || zipCompression; + var compression = compressions[compressionName]; + if (!compression) { + throw new Error(compressionName + " is not a valid compression method !"); + } + return compression; +}; + +/** + * Create a worker to generate a zip file. + * @param {JSZip} zip the JSZip instance at the right root level. + * @param {Object} options to generate the zip file. + * @param {String} comment the comment to use. + */ +exports.generateWorker = function (zip, options, comment) { + + var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName); + var entriesCount = 0; + try { + + zip.forEach(function (relativePath, file) { + entriesCount++; + var compression = getCompression(file.options.compression, options.compression); + var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; + var dir = file.dir, date = file.date; + + file._compressWorker(compression, compressionOptions) + .withStreamInfo("file", { + name : relativePath, + dir : dir, + date : date, + comment : file.comment || "", + unixPermissions : file.unixPermissions, + dosPermissions : file.dosPermissions + }) + .pipe(zipFileWorker); + }); + zipFileWorker.entriesCount = entriesCount; + } catch (e) { + zipFileWorker.error(e); + } + + return zipFileWorker; +}; + +},{"../compressions":3,"./ZipFileWorker":8}],10:[function(require,module,exports){ +'use strict'; + +/** + * Representation a of zip file in js + * @constructor + */ +function JSZip() { + // if this constructor is used without `new`, it adds `new` before itself: + if(!(this instanceof JSZip)) { + return new JSZip(); + } + + if(arguments.length) { + throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); + } + + // object containing the files : + // { + // "folder/" : {...}, + // "folder/data.txt" : {...} + // } + this.files = {}; + + this.comment = null; + + // Where we are in the hierarchy + this.root = ""; + this.clone = function() { + var newObj = new JSZip(); + for (var i in this) { + if (typeof this[i] !== "function") { + newObj[i] = this[i]; + } + } + return newObj; + }; +} +JSZip.prototype = require('./object'); +JSZip.prototype.loadAsync = require('./load'); +JSZip.support = require('./support'); +JSZip.defaults = require('./defaults'); + +// TODO find a better way to handle this version, +// a require('package.json').version doesn't work with webpack, see #327 +JSZip.version = "3.1.5"; + +JSZip.loadAsync = function (content, options) { + return new JSZip().loadAsync(content, options); +}; + +JSZip.external = require("./external"); +module.exports = JSZip; + +},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(require,module,exports){ +'use strict'; +var utils = require('./utils'); +var external = require("./external"); +var utf8 = require('./utf8'); +var utils = require('./utils'); +var ZipEntries = require('./zipEntries'); +var Crc32Probe = require('./stream/Crc32Probe'); +var nodejsUtils = require("./nodejsUtils"); + +/** + * Check the CRC32 of an entry. + * @param {ZipEntry} zipEntry the zip entry to check. + * @return {Promise} the result. + */ +function checkEntryCRC32(zipEntry) { + return new external.Promise(function (resolve, reject) { + var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe()); + worker.on("error", function (e) { + reject(e); + }) + .on("end", function () { + if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) { + reject(new Error("Corrupted zip : CRC32 mismatch")); + } else { + resolve(); + } + }) + .resume(); + }); +} + +module.exports = function(data, options) { + var zip = this; + options = utils.extend(options || {}, { + base64: false, + checkCRC32: false, + optimizedBinaryString: false, + createFolders: false, + decodeFileName: utf8.utf8decode + }); + + if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + return external.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")); + } + + return utils.prepareContent("the loaded zip file", data, true, options.optimizedBinaryString, options.base64) + .then(function(data) { + var zipEntries = new ZipEntries(options); + zipEntries.load(data); + return zipEntries; + }).then(function checkCRC32(zipEntries) { + var promises = [external.Promise.resolve(zipEntries)]; + var files = zipEntries.files; + if (options.checkCRC32) { + for (var i = 0; i < files.length; i++) { + promises.push(checkEntryCRC32(files[i])); + } + } + return external.Promise.all(promises); + }).then(function addFiles(results) { + var zipEntries = results.shift(); + var files = zipEntries.files; + for (var i = 0; i < files.length; i++) { + var input = files[i]; + zip.file(input.fileNameStr, input.decompressed, { + binary: true, + optimizedBinaryString: true, + date: input.date, + dir: input.dir, + comment : input.fileCommentStr.length ? input.fileCommentStr : null, + unixPermissions : input.unixPermissions, + dosPermissions : input.dosPermissions, + createFolders: options.createFolders + }); + } + if (zipEntries.zipComment.length) { + zip.comment = zipEntries.zipComment; + } + + return zip; + }); +}; + +},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(require,module,exports){ +"use strict"; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); + +/** + * A worker that use a nodejs stream as source. + * @constructor + * @param {String} filename the name of the file entry for this stream. + * @param {Readable} stream the nodejs stream. + */ +function NodejsStreamInputAdapter(filename, stream) { + GenericWorker.call(this, "Nodejs stream input adapter for " + filename); + this._upstreamEnded = false; + this._bindStream(stream); +} + +utils.inherits(NodejsStreamInputAdapter, GenericWorker); + +/** + * Prepare the stream and bind the callbacks on it. + * Do this ASAP on node 0.10 ! A lazy binding doesn't always work. + * @param {Stream} stream the nodejs stream to use. + */ +NodejsStreamInputAdapter.prototype._bindStream = function (stream) { + var self = this; + this._stream = stream; + stream.pause(); + stream + .on("data", function (chunk) { + self.push({ + data: chunk, + meta : { + percent : 0 + } + }); + }) + .on("error", function (e) { + if(self.isPaused) { + this.generatedError = e; + } else { + self.error(e); + } + }) + .on("end", function () { + if(self.isPaused) { + self._upstreamEnded = true; + } else { + self.end(); + } + }); +}; +NodejsStreamInputAdapter.prototype.pause = function () { + if(!GenericWorker.prototype.pause.call(this)) { + return false; + } + this._stream.pause(); + return true; +}; +NodejsStreamInputAdapter.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if(this._upstreamEnded) { + this.end(); + } else { + this._stream.resume(); + } + + return true; +}; + +module.exports = NodejsStreamInputAdapter; + +},{"../stream/GenericWorker":28,"../utils":32}],13:[function(require,module,exports){ +'use strict'; + +var Readable = require('readable-stream').Readable; + +var utils = require('../utils'); +utils.inherits(NodejsStreamOutputAdapter, Readable); + +/** +* A nodejs stream using a worker as source. +* @see the SourceWrapper in http://nodejs.org/api/stream.html +* @constructor +* @param {StreamHelper} helper the helper wrapping the worker +* @param {Object} options the nodejs stream options +* @param {Function} updateCb the update callback. +*/ +function NodejsStreamOutputAdapter(helper, options, updateCb) { + Readable.call(this, options); + this._helper = helper; + + var self = this; + helper.on("data", function (data, meta) { + if (!self.push(data)) { + self._helper.pause(); + } + if(updateCb) { + updateCb(meta); + } + }) + .on("error", function(e) { + self.emit('error', e); + }) + .on("end", function () { + self.push(null); + }); +} + + +NodejsStreamOutputAdapter.prototype._read = function() { + this._helper.resume(); +}; + +module.exports = NodejsStreamOutputAdapter; + +},{"../utils":32,"readable-stream":16}],14:[function(require,module,exports){ +'use strict'; + +module.exports = { + /** + * True if this is running in Nodejs, will be undefined in a browser. + * In a browser, browserify won't include this file and the whole module + * will be resolved an empty object. + */ + isNode : typeof Buffer !== "undefined", + /** + * Create a new nodejs Buffer from an existing content. + * @param {Object} data the data to pass to the constructor. + * @param {String} encoding the encoding to use. + * @return {Buffer} a new Buffer. + */ + newBufferFrom: function(data, encoding) { + // XXX We can't use `Buffer.from` which comes from `Uint8Array.from` + // in nodejs v4 (< v.4.5). It's not the expected implementation (and + // has a different signature). + // see https://github.com/nodejs/node/issues/8053 + // A condition on nodejs' version won't solve the issue as we don't + // control the Buffer polyfills that may or may not be used. + return new Buffer(data, encoding); + }, + /** + * Create a new nodejs Buffer with the specified size. + * @param {Integer} size the size of the buffer. + * @return {Buffer} a new Buffer. + */ + allocBuffer: function (size) { + if (Buffer.alloc) { + return Buffer.alloc(size); + } else { + return new Buffer(size); + } + }, + /** + * Find out if an object is a Buffer. + * @param {Object} b the object to test. + * @return {Boolean} true if the object is a Buffer, false otherwise. + */ + isBuffer : function(b){ + return Buffer.isBuffer(b); + }, + + isStream : function (obj) { + return obj && + typeof obj.on === "function" && + typeof obj.pause === "function" && + typeof obj.resume === "function"; + } +}; + +},{}],15:[function(require,module,exports){ +'use strict'; +var utf8 = require('./utf8'); +var utils = require('./utils'); +var GenericWorker = require('./stream/GenericWorker'); +var StreamHelper = require('./stream/StreamHelper'); +var defaults = require('./defaults'); +var CompressedObject = require('./compressedObject'); +var ZipObject = require('./zipObject'); +var generate = require("./generate"); +var nodejsUtils = require("./nodejsUtils"); +var NodejsStreamInputAdapter = require("./nodejs/NodejsStreamInputAdapter"); + + +/** + * Add a file in the current folder. + * @private + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file + * @param {Object} originalOptions the options of the file + * @return {Object} the new file. + */ +var fileAdd = function(name, data, originalOptions) { + // be sure sub folders exist + var dataType = utils.getTypeOf(data), + parent; + + + /* + * Correct options. + */ + + var o = utils.extend(originalOptions || {}, defaults); + o.date = o.date || new Date(); + if (o.compression !== null) { + o.compression = o.compression.toUpperCase(); + } + + if (typeof o.unixPermissions === "string") { + o.unixPermissions = parseInt(o.unixPermissions, 8); + } + + // UNX_IFDIR 0040000 see zipinfo.c + if (o.unixPermissions && (o.unixPermissions & 0x4000)) { + o.dir = true; + } + // Bit 4 Directory + if (o.dosPermissions && (o.dosPermissions & 0x0010)) { + o.dir = true; + } + + if (o.dir) { + name = forceTrailingSlash(name); + } + if (o.createFolders && (parent = parentFolder(name))) { + folderAdd.call(this, parent, true); + } + + var isUnicodeString = dataType === "string" && o.binary === false && o.base64 === false; + if (!originalOptions || typeof originalOptions.binary === "undefined") { + o.binary = !isUnicodeString; + } + + + var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0; + + if (isCompressedEmpty || o.dir || !data || data.length === 0) { + o.base64 = false; + o.binary = true; + data = ""; + o.compression = "STORE"; + dataType = "string"; + } + + /* + * Convert content to fit. + */ + + var zipObjectContent = null; + if (data instanceof CompressedObject || data instanceof GenericWorker) { + zipObjectContent = data; + } else if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + zipObjectContent = new NodejsStreamInputAdapter(name, data); + } else { + zipObjectContent = utils.prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64); + } + + var object = new ZipObject(name, zipObjectContent, o); + this.files[name] = object; + /* + TODO: we can't throw an exception because we have async promises + (we can have a promise of a Date() for example) but returning a + promise is useless because file(name, data) returns the JSZip + object for chaining. Should we break that to allow the user + to catch the error ? + + return external.Promise.resolve(zipObjectContent) + .then(function () { + return object; + }); + */ +}; + +/** + * Find the parent folder of the path. + * @private + * @param {string} path the path to use + * @return {string} the parent folder, or "" + */ +var parentFolder = function (path) { + if (path.slice(-1) === '/') { + path = path.substring(0, path.length - 1); + } + var lastSlash = path.lastIndexOf('/'); + return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; +}; + +/** + * Returns the path with a slash at the end. + * @private + * @param {String} path the path to check. + * @return {String} the path with a trailing slash. + */ +var forceTrailingSlash = function(path) { + // Check the name ends with a / + if (path.slice(-1) !== "/") { + path += "/"; // IE doesn't like substr(-1) + } + return path; +}; + +/** + * Add a (sub) folder in the current folder. + * @private + * @param {string} name the folder's name + * @param {boolean=} [createFolders] If true, automatically create sub + * folders. Defaults to false. + * @return {Object} the new folder. + */ +var folderAdd = function(name, createFolders) { + createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders; + + name = forceTrailingSlash(name); + + // Does this folder already exist? + if (!this.files[name]) { + fileAdd.call(this, name, null, { + dir: true, + createFolders: createFolders + }); + } + return this.files[name]; +}; + +/** +* Cross-window, cross-Node-context regular expression detection +* @param {Object} object Anything +* @return {Boolean} true if the object is a regular expression, +* false otherwise +*/ +function isRegExp(object) { + return Object.prototype.toString.call(object) === "[object RegExp]"; +} + +// return the actual prototype of JSZip +var out = { + /** + * @see loadAsync + */ + load: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + + /** + * Call a callback function for each entry at this folder level. + * @param {Function} cb the callback function: + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + */ + forEach: function(cb) { + var filename, relativePath, file; + for (filename in this.files) { + if (!this.files.hasOwnProperty(filename)) { + continue; + } + file = this.files[filename]; + relativePath = filename.slice(this.root.length, filename.length); + if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root + cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn... + } + } + }, + + /** + * Filter nested files/folders with the specified function. + * @param {Function} search the predicate to use : + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + * @return {Array} An array of matching elements. + */ + filter: function(search) { + var result = []; + this.forEach(function (relativePath, entry) { + if (search(relativePath, entry)) { // the file matches the function + result.push(entry); + } + + }); + return result; + }, + + /** + * Add a file to the zip file, or search a file. + * @param {string|RegExp} name The name of the file to add (if data is defined), + * the name of the file to find (if no data) or a regex to match files. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded + * @param {Object} o File options + * @return {JSZip|Object|Array} this JSZip object (when adding a file), + * a file (when searching by string) or an array of files (when searching by regex). + */ + file: function(name, data, o) { + if (arguments.length === 1) { + if (isRegExp(name)) { + var regexp = name; + return this.filter(function(relativePath, file) { + return !file.dir && regexp.test(relativePath); + }); + } + else { // text + var obj = this.files[this.root + name]; + if (obj && !obj.dir) { + return obj; + } else { + return null; + } + } + } + else { // more than one argument : we have data ! + name = this.root + name; + fileAdd.call(this, name, data, o); + } + return this; + }, + + /** + * Add a directory to the zip file, or search. + * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. + * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. + */ + folder: function(arg) { + if (!arg) { + return this; + } + + if (isRegExp(arg)) { + return this.filter(function(relativePath, file) { + return file.dir && arg.test(relativePath); + }); + } + + // else, name is a new folder + var name = this.root + arg; + var newFolder = folderAdd.call(this, name); + + // Allow chaining by returning a new object with this folder as the root + var ret = this.clone(); + ret.root = newFolder.name; + return ret; + }, + + /** + * Delete a file, or a directory and all sub-files, from the zip + * @param {string} name the name of the file to delete + * @return {JSZip} this JSZip object + */ + remove: function(name) { + name = this.root + name; + var file = this.files[name]; + if (!file) { + // Look for any folders + if (name.slice(-1) !== "/") { + name += "/"; + } + file = this.files[name]; + } + + if (file && !file.dir) { + // file + delete this.files[name]; + } else { + // maybe a folder, delete recursively + var kids = this.filter(function(relativePath, file) { + return file.name.slice(0, name.length) === name; + }); + for (var i = 0; i < kids.length; i++) { + delete this.files[kids[i].name]; + } + } + + return this; + }, + + /** + * Generate the complete zip file + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file + */ + generate: function(options) { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + /** + * Generate the complete zip file as an internal stream. + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {StreamHelper} the streamed zip file. + */ + generateInternalStream: function(options) { + var worker, opts = {}; + try { + opts = utils.extend(options || {}, { + streamFiles: false, + compression: "STORE", + compressionOptions : null, + type: "", + platform: "DOS", + comment: null, + mimeType: 'application/zip', + encodeFileName: utf8.utf8encode + }); + + opts.type = opts.type.toLowerCase(); + opts.compression = opts.compression.toUpperCase(); + + // "binarystring" is prefered but the internals use "string". + if(opts.type === "binarystring") { + opts.type = "string"; + } + + if (!opts.type) { + throw new Error("No output type specified."); + } + + utils.checkSupport(opts.type); + + // accept nodejs `process.platform` + if( + opts.platform === 'darwin' || + opts.platform === 'freebsd' || + opts.platform === 'linux' || + opts.platform === 'sunos' + ) { + opts.platform = "UNIX"; + } + if (opts.platform === 'win32') { + opts.platform = "DOS"; + } + + var comment = opts.comment || this.comment || ""; + worker = generate.generateWorker(this, opts, comment); + } catch (e) { + worker = new GenericWorker("error"); + worker.error(e); + } + return new StreamHelper(worker, opts.type || "string", opts.mimeType); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateAsync: function(options, onUpdate) { + return this.generateInternalStream(options).accumulate(onUpdate); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateNodeStream: function(options, onUpdate) { + options = options || {}; + if (!options.type) { + options.type = "nodebuffer"; + } + return this.generateInternalStream(options).toNodejsStream(onUpdate); + } +}; +module.exports = out; + +},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(require,module,exports){ +/* + * This file is used by module bundlers (browserify/webpack/etc) when + * including a stream implementation. We use "readable-stream" to get a + * consistent behavior between nodejs versions but bundlers often have a shim + * for "stream". Using this shim greatly improve the compatibility and greatly + * reduce the final size of the bundle (only one stream implementation, not + * two). + */ +module.exports = require("stream"); + +},{"stream":undefined}],17:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function ArrayReader(data) { + DataReader.call(this, data); + for(var i = 0; i < this.data.length; i++) { + data[i] = data[i] & 0xFF; + } +} +utils.inherits(ArrayReader, DataReader); +/** + * @see DataReader.byteAt + */ +ArrayReader.prototype.byteAt = function(i) { + return this.data[this.zero + i]; +}; +/** + * @see DataReader.lastIndexOfSignature + */ +ArrayReader.prototype.lastIndexOfSignature = function(sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3); + for (var i = this.length - 4; i >= 0; --i) { + if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { + return i - this.zero; + } + } + + return -1; +}; +/** + * @see DataReader.readAndCheckSignature + */ +ArrayReader.prototype.readAndCheckSignature = function (sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3), + data = this.readData(4); + return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3]; +}; +/** + * @see DataReader.readData + */ +ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + return []; + } + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = ArrayReader; + +},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){ +'use strict'; +var utils = require('../utils'); + +function DataReader(data) { + this.data = data; // type : see implementation + this.length = data.length; + this.index = 0; + this.zero = 0; +} +DataReader.prototype = { + /** + * Check that the offset will not go too far. + * @param {string} offset the additional offset to check. + * @throws {Error} an Error if the offset is out of bounds. + */ + checkOffset: function(offset) { + this.checkIndex(this.index + offset); + }, + /** + * Check that the specified index will not be too far. + * @param {string} newIndex the index to check. + * @throws {Error} an Error if the index is out of bounds. + */ + checkIndex: function(newIndex) { + if (this.length < this.zero + newIndex || newIndex < 0) { + throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); + } + }, + /** + * Change the index. + * @param {number} newIndex The new index. + * @throws {Error} if the new index is out of the data. + */ + setIndex: function(newIndex) { + this.checkIndex(newIndex); + this.index = newIndex; + }, + /** + * Skip the next n bytes. + * @param {number} n the number of bytes to skip. + * @throws {Error} if the new index is out of the data. + */ + skip: function(n) { + this.setIndex(this.index + n); + }, + /** + * Get the byte at the specified index. + * @param {number} i the index to use. + * @return {number} a byte. + */ + byteAt: function(i) { + // see implementations + }, + /** + * Get the next number with a given byte size. + * @param {number} size the number of bytes to read. + * @return {number} the corresponding number. + */ + readInt: function(size) { + var result = 0, + i; + this.checkOffset(size); + for (i = this.index + size - 1; i >= this.index; i--) { + result = (result << 8) + this.byteAt(i); + } + this.index += size; + return result; + }, + /** + * Get the next string with a given byte size. + * @param {number} size the number of bytes to read. + * @return {string} the corresponding string. + */ + readString: function(size) { + return utils.transformTo("string", this.readData(size)); + }, + /** + * Get raw data without conversion, bytes. + * @param {number} size the number of bytes to read. + * @return {Object} the raw data, implementation specific. + */ + readData: function(size) { + // see implementations + }, + /** + * Find the last occurence of a zip signature (4 bytes). + * @param {string} sig the signature to find. + * @return {number} the index of the last occurence, -1 if not found. + */ + lastIndexOfSignature: function(sig) { + // see implementations + }, + /** + * Read the signature (4 bytes) at the current position and compare it with sig. + * @param {string} sig the expected signature + * @return {boolean} true if the signature matches, false otherwise. + */ + readAndCheckSignature: function(sig) { + // see implementations + }, + /** + * Get the next date. + * @return {Date} the date. + */ + readDate: function() { + var dostime = this.readInt(4); + return new Date(Date.UTC( + ((dostime >> 25) & 0x7f) + 1980, // year + ((dostime >> 21) & 0x0f) - 1, // month + (dostime >> 16) & 0x1f, // day + (dostime >> 11) & 0x1f, // hour + (dostime >> 5) & 0x3f, // minute + (dostime & 0x1f) << 1)); // second + } +}; +module.exports = DataReader; + +},{"../utils":32}],19:[function(require,module,exports){ +'use strict'; +var Uint8ArrayReader = require('./Uint8ArrayReader'); +var utils = require('../utils'); + +function NodeBufferReader(data) { + Uint8ArrayReader.call(this, data); +} +utils.inherits(NodeBufferReader, Uint8ArrayReader); + +/** + * @see DataReader.readData + */ +NodeBufferReader.prototype.readData = function(size) { + this.checkOffset(size); + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = NodeBufferReader; + +},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function StringReader(data) { + DataReader.call(this, data); +} +utils.inherits(StringReader, DataReader); +/** + * @see DataReader.byteAt + */ +StringReader.prototype.byteAt = function(i) { + return this.data.charCodeAt(this.zero + i); +}; +/** + * @see DataReader.lastIndexOfSignature + */ +StringReader.prototype.lastIndexOfSignature = function(sig) { + return this.data.lastIndexOf(sig) - this.zero; +}; +/** + * @see DataReader.readAndCheckSignature + */ +StringReader.prototype.readAndCheckSignature = function (sig) { + var data = this.readData(4); + return sig === data; +}; +/** + * @see DataReader.readData + */ +StringReader.prototype.readData = function(size) { + this.checkOffset(size); + // this will work because the constructor applied the "& 0xff" mask. + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = StringReader; + +},{"../utils":32,"./DataReader":18}],21:[function(require,module,exports){ +'use strict'; +var ArrayReader = require('./ArrayReader'); +var utils = require('../utils'); + +function Uint8ArrayReader(data) { + ArrayReader.call(this, data); +} +utils.inherits(Uint8ArrayReader, ArrayReader); +/** + * @see DataReader.readData + */ +Uint8ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. + return new Uint8Array(0); + } + var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = Uint8ArrayReader; + +},{"../utils":32,"./ArrayReader":17}],22:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var support = require('../support'); +var ArrayReader = require('./ArrayReader'); +var StringReader = require('./StringReader'); +var NodeBufferReader = require('./NodeBufferReader'); +var Uint8ArrayReader = require('./Uint8ArrayReader'); + +/** + * Create a reader adapted to the data. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read. + * @return {DataReader} the data reader. + */ +module.exports = function (data) { + var type = utils.getTypeOf(data); + utils.checkSupport(type); + if (type === "string" && !support.uint8array) { + return new StringReader(data); + } + if (type === "nodebuffer") { + return new NodeBufferReader(data); + } + if (support.uint8array) { + return new Uint8ArrayReader(utils.transformTo("uint8array", data)); + } + return new ArrayReader(utils.transformTo("array", data)); +}; + +},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(require,module,exports){ +'use strict'; +exports.LOCAL_FILE_HEADER = "PK\x03\x04"; +exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; +exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; +exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; +exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; +exports.DATA_DESCRIPTOR = "PK\x07\x08"; + +},{}],24:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var utils = require('../utils'); + +/** + * A worker which convert chunks to a specified type. + * @constructor + * @param {String} destType the destination type. + */ +function ConvertWorker(destType) { + GenericWorker.call(this, "ConvertWorker to " + destType); + this.destType = destType; +} +utils.inherits(ConvertWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +ConvertWorker.prototype.processChunk = function (chunk) { + this.push({ + data : utils.transformTo(this.destType, chunk.data), + meta : chunk.meta + }); +}; +module.exports = ConvertWorker; + +},{"../utils":32,"./GenericWorker":28}],25:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var crc32 = require('../crc32'); +var utils = require('../utils'); + +/** + * A worker which calculate the crc32 of the data flowing through. + * @constructor + */ +function Crc32Probe() { + GenericWorker.call(this, "Crc32Probe"); + this.withStreamInfo("crc32", 0); +} +utils.inherits(Crc32Probe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Crc32Probe.prototype.processChunk = function (chunk) { + this.streamInfo.crc32 = crc32(chunk.data, this.streamInfo.crc32 || 0); + this.push(chunk); +}; +module.exports = Crc32Probe; + +},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +/** + * A worker which calculate the total length of the data flowing through. + * @constructor + * @param {String} propName the name used to expose the length + */ +function DataLengthProbe(propName) { + GenericWorker.call(this, "DataLengthProbe for " + propName); + this.propName = propName; + this.withStreamInfo(propName, 0); +} +utils.inherits(DataLengthProbe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +DataLengthProbe.prototype.processChunk = function (chunk) { + if(chunk) { + var length = this.streamInfo[this.propName] || 0; + this.streamInfo[this.propName] = length + chunk.data.length; + } + GenericWorker.prototype.processChunk.call(this, chunk); +}; +module.exports = DataLengthProbe; + + +},{"../utils":32,"./GenericWorker":28}],27:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +// the size of the generated chunks +// TODO expose this as a public variable +var DEFAULT_BLOCK_SIZE = 16 * 1024; + +/** + * A worker that reads a content and emits chunks. + * @constructor + * @param {Promise} dataP the promise of the data to split + */ +function DataWorker(dataP) { + GenericWorker.call(this, "DataWorker"); + var self = this; + this.dataIsReady = false; + this.index = 0; + this.max = 0; + this.data = null; + this.type = ""; + + this._tickScheduled = false; + + dataP.then(function (data) { + self.dataIsReady = true; + self.data = data; + self.max = data && data.length || 0; + self.type = utils.getTypeOf(data); + if(!self.isPaused) { + self._tickAndRepeat(); + } + }, function (e) { + self.error(e); + }); +} + +utils.inherits(DataWorker, GenericWorker); + +/** + * @see GenericWorker.cleanUp + */ +DataWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this.data = null; +}; + +/** + * @see GenericWorker.resume + */ +DataWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this._tickScheduled && this.dataIsReady) { + this._tickScheduled = true; + utils.delay(this._tickAndRepeat, [], this); + } + return true; +}; + +/** + * Trigger a tick a schedule an other call to this function. + */ +DataWorker.prototype._tickAndRepeat = function() { + this._tickScheduled = false; + if(this.isPaused || this.isFinished) { + return; + } + this._tick(); + if(!this.isFinished) { + utils.delay(this._tickAndRepeat, [], this); + this._tickScheduled = true; + } +}; + +/** + * Read and push a chunk. + */ +DataWorker.prototype._tick = function() { + + if(this.isPaused || this.isFinished) { + return false; + } + + var size = DEFAULT_BLOCK_SIZE; + var data = null, nextIndex = Math.min(this.max, this.index + size); + if (this.index >= this.max) { + // EOF + return this.end(); + } else { + switch(this.type) { + case "string": + data = this.data.substring(this.index, nextIndex); + break; + case "uint8array": + data = this.data.subarray(this.index, nextIndex); + break; + case "array": + case "nodebuffer": + data = this.data.slice(this.index, nextIndex); + break; + } + this.index = nextIndex; + return this.push({ + data : data, + meta : { + percent : this.max ? this.index / this.max * 100 : 0 + } + }); + } +}; + +module.exports = DataWorker; + +},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){ +'use strict'; + +/** + * A worker that does nothing but passing chunks to the next one. This is like + * a nodejs stream but with some differences. On the good side : + * - it works on IE 6-9 without any issue / polyfill + * - it weights less than the full dependencies bundled with browserify + * - it forwards errors (no need to declare an error handler EVERYWHERE) + * + * A chunk is an object with 2 attributes : `meta` and `data`. The former is an + * object containing anything (`percent` for example), see each worker for more + * details. The latter is the real data (String, Uint8Array, etc). + * + * @constructor + * @param {String} name the name of the stream (mainly used for debugging purposes) + */ +function GenericWorker(name) { + // the name of the worker + this.name = name || "default"; + // an object containing metadata about the workers chain + this.streamInfo = {}; + // an error which happened when the worker was paused + this.generatedError = null; + // an object containing metadata to be merged by this worker into the general metadata + this.extraStreamInfo = {}; + // true if the stream is paused (and should not do anything), false otherwise + this.isPaused = true; + // true if the stream is finished (and should not do anything), false otherwise + this.isFinished = false; + // true if the stream is locked to prevent further structure updates (pipe), false otherwise + this.isLocked = false; + // the event listeners + this._listeners = { + 'data':[], + 'end':[], + 'error':[] + }; + // the previous worker, if any + this.previous = null; +} + +GenericWorker.prototype = { + /** + * Push a chunk to the next workers. + * @param {Object} chunk the chunk to push + */ + push : function (chunk) { + this.emit("data", chunk); + }, + /** + * End the stream. + * @return {Boolean} true if this call ended the worker, false otherwise. + */ + end : function () { + if (this.isFinished) { + return false; + } + + this.flush(); + try { + this.emit("end"); + this.cleanUp(); + this.isFinished = true; + } catch (e) { + this.emit("error", e); + } + return true; + }, + /** + * End the stream with an error. + * @param {Error} e the error which caused the premature end. + * @return {Boolean} true if this call ended the worker with an error, false otherwise. + */ + error : function (e) { + if (this.isFinished) { + return false; + } + + if(this.isPaused) { + this.generatedError = e; + } else { + this.isFinished = true; + + this.emit("error", e); + + // in the workers chain exploded in the middle of the chain, + // the error event will go downward but we also need to notify + // workers upward that there has been an error. + if(this.previous) { + this.previous.error(e); + } + + this.cleanUp(); + } + return true; + }, + /** + * Add a callback on an event. + * @param {String} name the name of the event (data, end, error) + * @param {Function} listener the function to call when the event is triggered + * @return {GenericWorker} the current object for chainability + */ + on : function (name, listener) { + this._listeners[name].push(listener); + return this; + }, + /** + * Clean any references when a worker is ending. + */ + cleanUp : function () { + this.streamInfo = this.generatedError = this.extraStreamInfo = null; + this._listeners = []; + }, + /** + * Trigger an event. This will call registered callback with the provided arg. + * @param {String} name the name of the event (data, end, error) + * @param {Object} arg the argument to call the callback with. + */ + emit : function (name, arg) { + if (this._listeners[name]) { + for(var i = 0; i < this._listeners[name].length; i++) { + this._listeners[name][i].call(this, arg); + } + } + }, + /** + * Chain a worker with an other. + * @param {Worker} next the worker receiving events from the current one. + * @return {worker} the next worker for chainability + */ + pipe : function (next) { + return next.registerPrevious(this); + }, + /** + * Same as `pipe` in the other direction. + * Using an API with `pipe(next)` is very easy. + * Implementing the API with the point of view of the next one registering + * a source is easier, see the ZipFileWorker. + * @param {Worker} previous the previous worker, sending events to this one + * @return {Worker} the current worker for chainability + */ + registerPrevious : function (previous) { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + + // sharing the streamInfo... + this.streamInfo = previous.streamInfo; + // ... and adding our own bits + this.mergeStreamInfo(); + this.previous = previous; + var self = this; + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.end(); + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; + }, + /** + * Pause the stream so it doesn't send events anymore. + * @return {Boolean} true if this call paused the worker, false otherwise. + */ + pause : function () { + if(this.isPaused || this.isFinished) { + return false; + } + this.isPaused = true; + + if(this.previous) { + this.previous.pause(); + } + return true; + }, + /** + * Resume a paused stream. + * @return {Boolean} true if this call resumed the worker, false otherwise. + */ + resume : function () { + if(!this.isPaused || this.isFinished) { + return false; + } + this.isPaused = false; + + // if true, the worker tried to resume but failed + var withError = false; + if(this.generatedError) { + this.error(this.generatedError); + withError = true; + } + if(this.previous) { + this.previous.resume(); + } + + return !withError; + }, + /** + * Flush any remaining bytes as the stream is ending. + */ + flush : function () {}, + /** + * Process a chunk. This is usually the method overridden. + * @param {Object} chunk the chunk to process. + */ + processChunk : function(chunk) { + this.push(chunk); + }, + /** + * Add a key/value to be added in the workers chain streamInfo once activated. + * @param {String} key the key to use + * @param {Object} value the associated value + * @return {Worker} the current worker for chainability + */ + withStreamInfo : function (key, value) { + this.extraStreamInfo[key] = value; + this.mergeStreamInfo(); + return this; + }, + /** + * Merge this worker's streamInfo into the chain's streamInfo. + */ + mergeStreamInfo : function () { + for(var key in this.extraStreamInfo) { + if (!this.extraStreamInfo.hasOwnProperty(key)) { + continue; + } + this.streamInfo[key] = this.extraStreamInfo[key]; + } + }, + + /** + * Lock the stream to prevent further updates on the workers chain. + * After calling this method, all calls to pipe will fail. + */ + lock: function () { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + this.isLocked = true; + if (this.previous) { + this.previous.lock(); + } + }, + + /** + * + * Pretty print the workers chain. + */ + toString : function () { + var me = "Worker " + this.name; + if (this.previous) { + return this.previous + " -> " + me; + } else { + return me; + } + } +}; + +module.exports = GenericWorker; + +},{}],29:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var ConvertWorker = require('./ConvertWorker'); +var GenericWorker = require('./GenericWorker'); +var base64 = require('../base64'); +var support = require("../support"); +var external = require("../external"); + +var NodejsStreamOutputAdapter = null; +if (support.nodestream) { + try { + NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter'); + } catch(e) {} +} + +/** + * Apply the final transformation of the data. If the user wants a Blob for + * example, it's easier to work with an U8intArray and finally do the + * ArrayBuffer/Blob conversion. + * @param {String} type the name of the final type + * @param {String|Uint8Array|Buffer} content the content to transform + * @param {String} mimeType the mime type of the content, if applicable. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. + */ +function transformZipOutput(type, content, mimeType) { + switch(type) { + case "blob" : + return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); + case "base64" : + return base64.encode(content); + default : + return utils.transformTo(type, content); + } +} + +/** + * Concatenate an array of data of the given type. + * @param {String} type the type of the data in the given array. + * @param {Array} dataArray the array containing the data chunks to concatenate + * @return {String|Uint8Array|Buffer} the concatenated data + * @throws Error if the asked type is unsupported + */ +function concat (type, dataArray) { + var i, index = 0, res = null, totalLength = 0; + for(i = 0; i < dataArray.length; i++) { + totalLength += dataArray[i].length; + } + switch(type) { + case "string": + return dataArray.join(""); + case "array": + return Array.prototype.concat.apply([], dataArray); + case "uint8array": + res = new Uint8Array(totalLength); + for(i = 0; i < dataArray.length; i++) { + res.set(dataArray[i], index); + index += dataArray[i].length; + } + return res; + case "nodebuffer": + return Buffer.concat(dataArray); + default: + throw new Error("concat : unsupported type '" + type + "'"); + } +} + +/** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {StreamHelper} helper the helper to use. + * @param {Function} updateCallback a callback called on each update. Called + * with one arg : + * - the metadata linked to the update received. + * @return Promise the promise for the accumulation. + */ +function accumulate(helper, updateCallback) { + return new external.Promise(function (resolve, reject){ + var dataArray = []; + var chunkType = helper._internalType, + resultType = helper._outputType, + mimeType = helper._mimeType; + helper + .on('data', function (data, meta) { + dataArray.push(data); + if(updateCallback) { + updateCallback(meta); + } + }) + .on('error', function(err) { + dataArray = []; + reject(err); + }) + .on('end', function (){ + try { + var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); + resolve(result); + } catch (e) { + reject(e); + } + dataArray = []; + }) + .resume(); + }); +} + +/** + * An helper to easily use workers outside of JSZip. + * @constructor + * @param {Worker} worker the worker to wrap + * @param {String} outputType the type of data expected by the use + * @param {String} mimeType the mime type of the content, if applicable. + */ +function StreamHelper(worker, outputType, mimeType) { + var internalType = outputType; + switch(outputType) { + case "blob": + case "arraybuffer": + internalType = "uint8array"; + break; + case "base64": + internalType = "string"; + break; + } + + try { + // the type used internally + this._internalType = internalType; + // the type used to output results + this._outputType = outputType; + // the mime type + this._mimeType = mimeType; + utils.checkSupport(internalType); + this._worker = worker.pipe(new ConvertWorker(internalType)); + // the last workers can be rewired without issues but we need to + // prevent any updates on previous workers. + worker.lock(); + } catch(e) { + this._worker = new GenericWorker("error"); + this._worker.error(e); + } +} + +StreamHelper.prototype = { + /** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {Function} updateCb the update callback. + * @return Promise the promise for the accumulation. + */ + accumulate : function (updateCb) { + return accumulate(this, updateCb); + }, + /** + * Add a listener on an event triggered on a stream. + * @param {String} evt the name of the event + * @param {Function} fn the listener + * @return {StreamHelper} the current helper. + */ + on : function (evt, fn) { + var self = this; + + if(evt === "data") { + this._worker.on(evt, function (chunk) { + fn.call(self, chunk.data, chunk.meta); + }); + } else { + this._worker.on(evt, function () { + utils.delay(fn, arguments, self); + }); + } + return this; + }, + /** + * Resume the flow of chunks. + * @return {StreamHelper} the current helper. + */ + resume : function () { + utils.delay(this._worker.resume, [], this._worker); + return this; + }, + /** + * Pause the flow of chunks. + * @return {StreamHelper} the current helper. + */ + pause : function () { + this._worker.pause(); + return this; + }, + /** + * Return a nodejs stream for this helper. + * @param {Function} updateCb the update callback. + * @return {NodejsStreamOutputAdapter} the nodejs stream. + */ + toNodejsStream : function (updateCb) { + utils.checkSupport("nodestream"); + if (this._outputType !== "nodebuffer") { + // an object stream containing blob/arraybuffer/uint8array/string + // is strange and I don't know if it would be useful. + // I you find this comment and have a good usecase, please open a + // bug report ! + throw new Error(this._outputType + " is not supported by this method"); + } + + return new NodejsStreamOutputAdapter(this, { + objectMode : this._outputType !== "nodebuffer" + }, updateCb); + } +}; + + +module.exports = StreamHelper; + +},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(require,module,exports){ +'use strict'; + +exports.base64 = true; +exports.array = true; +exports.string = true; +exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; +exports.nodebuffer = typeof Buffer !== "undefined"; +// contains true if JSZip can read/generate Uint8Array, false otherwise. +exports.uint8array = typeof Uint8Array !== "undefined"; + +if (typeof ArrayBuffer === "undefined") { + exports.blob = false; +} +else { + var buffer = new ArrayBuffer(0); + try { + exports.blob = new Blob([buffer], { + type: "application/zip" + }).size === 0; + } + catch (e) { + try { + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + exports.blob = builder.getBlob('application/zip').size === 0; + } + catch (e) { + exports.blob = false; + } + } +} + +try { + exports.nodestream = !!require('readable-stream').Readable; +} catch(e) { + exports.nodestream = false; +} + +},{"readable-stream":16}],31:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var support = require('./support'); +var nodejsUtils = require('./nodejsUtils'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * The following functions come from pako, from pako/lib/utils/strings + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new Array(256); +for (var i=0; i<256; i++) { + _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); +} +_utf8len[254]=_utf8len[254]=1; // Invalid sequence start + +// convert string to array (typed, when possible) +var string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + if (support.uint8array) { + buf = new Uint8Array(buf_len); + } else { + buf = new Array(buf_len); + } + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +var utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +// convert array to string +var buf2string = function (buf) { + var str, i, out, c, c_len; + var len = buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + // shrinkBuf(utf16buf, out) + if (utf16buf.length !== out) { + if(utf16buf.subarray) { + utf16buf = utf16buf.subarray(0, out); + } else { + utf16buf.length = out; + } + } + + // return String.fromCharCode.apply(null, utf16buf); + return utils.applyFromCharCode(utf16buf); +}; + + +// That's all for the pako functions. + + +/** + * Transform a javascript string into an array (typed if possible) of bytes, + * UTF-8 encoded. + * @param {String} str the string to encode + * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. + */ +exports.utf8encode = function utf8encode(str) { + if (support.nodebuffer) { + return nodejsUtils.newBufferFrom(str, "utf-8"); + } + + return string2buf(str); +}; + + +/** + * Transform a bytes array (or a representation) representing an UTF-8 encoded + * string into a javascript string. + * @param {Array|Uint8Array|Buffer} buf the data de decode + * @return {String} the decoded string. + */ +exports.utf8decode = function utf8decode(buf) { + if (support.nodebuffer) { + return utils.transformTo("nodebuffer", buf).toString("utf-8"); + } + + buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); + + return buf2string(buf); +}; + +/** + * A worker to decode utf8 encoded binary chunks into string chunks. + * @constructor + */ +function Utf8DecodeWorker() { + GenericWorker.call(this, "utf-8 decode"); + // the last bytes if a chunk didn't end with a complete codepoint. + this.leftOver = null; +} +utils.inherits(Utf8DecodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8DecodeWorker.prototype.processChunk = function (chunk) { + + var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data); + + // 1st step, re-use what's left of the previous chunk + if (this.leftOver && this.leftOver.length) { + if(support.uint8array) { + var previousData = data; + data = new Uint8Array(previousData.length + this.leftOver.length); + data.set(this.leftOver, 0); + data.set(previousData, this.leftOver.length); + } else { + data = this.leftOver.concat(data); + } + this.leftOver = null; + } + + var nextBoundary = utf8border(data); + var usableData = data; + if (nextBoundary !== data.length) { + if (support.uint8array) { + usableData = data.subarray(0, nextBoundary); + this.leftOver = data.subarray(nextBoundary, data.length); + } else { + usableData = data.slice(0, nextBoundary); + this.leftOver = data.slice(nextBoundary, data.length); + } + } + + this.push({ + data : exports.utf8decode(usableData), + meta : chunk.meta + }); +}; + +/** + * @see GenericWorker.flush + */ +Utf8DecodeWorker.prototype.flush = function () { + if(this.leftOver && this.leftOver.length) { + this.push({ + data : exports.utf8decode(this.leftOver), + meta : {} + }); + this.leftOver = null; + } +}; +exports.Utf8DecodeWorker = Utf8DecodeWorker; + +/** + * A worker to endcode string chunks into utf8 encoded binary chunks. + * @constructor + */ +function Utf8EncodeWorker() { + GenericWorker.call(this, "utf-8 encode"); +} +utils.inherits(Utf8EncodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8EncodeWorker.prototype.processChunk = function (chunk) { + this.push({ + data : exports.utf8encode(chunk.data), + meta : chunk.meta + }); +}; +exports.Utf8EncodeWorker = Utf8EncodeWorker; + +},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){ +'use strict'; + +var support = require('./support'); +var base64 = require('./base64'); +var nodejsUtils = require('./nodejsUtils'); +var setImmediate = require('core-js/library/fn/set-immediate'); +var external = require("./external"); + + +/** + * Convert a string that pass as a "binary string": it should represent a byte + * array but may have > 255 char codes. Be sure to take only the first byte + * and returns the byte array. + * @param {String} str the string to transform. + * @return {Array|Uint8Array} the string in a binary format. + */ +function string2binary(str) { + var result = null; + if (support.uint8array) { + result = new Uint8Array(str.length); + } else { + result = new Array(str.length); + } + return stringToArrayLike(str, result); +} + +/** + * Create a new blob with the given content and the given type. + * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use + * an Uint8Array because the stock browser of android 4 won't accept it (it + * will be silently converted to a string, "[object Uint8Array]"). + * + * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: + * when a large amount of Array is used to create the Blob, the amount of + * memory consumed is nearly 100 times the original data amount. + * + * @param {String} type the mime type of the blob. + * @return {Blob} the created blob. + */ +exports.newBlob = function(part, type) { + exports.checkSupport("blob"); + + try { + // Blob constructor + return new Blob([part], { + type: type + }); + } + catch (e) { + + try { + // deprecated, browser only, old way + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(part); + return builder.getBlob(type); + } + catch (e) { + + // well, fuck ?! + throw new Error("Bug : can't construct the Blob."); + } + } + + +}; +/** + * The identity function. + * @param {Object} input the input. + * @return {Object} the same input. + */ +function identity(input) { + return input; +} + +/** + * Fill in an array with a string. + * @param {String} str the string to use. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. + */ +function stringToArrayLike(str, array) { + for (var i = 0; i < str.length; ++i) { + array[i] = str.charCodeAt(i) & 0xFF; + } + return array; +} + +/** + * An helper for the function arrayLikeToString. + * This contains static informations and functions that + * can be optimized by the browser JIT compiler. + */ +var arrayToStringHelper = { + /** + * Transform an array of int into a string, chunk by chunk. + * See the performances notes on arrayLikeToString. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @param {String} type the type of the array. + * @param {Integer} chunk the chunk size. + * @return {String} the resulting string. + * @throws Error if the chunk is too big for the stack. + */ + stringifyByChunk: function(array, type, chunk) { + var result = [], k = 0, len = array.length; + // shortcut + if (len <= chunk) { + return String.fromCharCode.apply(null, array); + } + while (k < len) { + if (type === "array" || type === "nodebuffer") { + result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); + } + else { + result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); + } + k += chunk; + } + return result.join(""); + }, + /** + * Call String.fromCharCode on every item in the array. + * This is the naive implementation, which generate A LOT of intermediate string. + * This should be used when everything else fail. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ + stringifyByChar: function(array){ + var resultStr = ""; + for(var i = 0; i < array.length; i++) { + resultStr += String.fromCharCode(array[i]); + } + return resultStr; + }, + applyCanBeUsed : { + /** + * true if the browser accepts to use String.fromCharCode on Uint8Array + */ + uint8array : (function () { + try { + return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; + } catch (e) { + return false; + } + })(), + /** + * true if the browser accepts to use String.fromCharCode on nodejs Buffer. + */ + nodebuffer : (function () { + try { + return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; + } catch (e) { + return false; + } + })() + } +}; + +/** + * Transform an array-like object to a string. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ +function arrayLikeToString(array) { + // Performances notes : + // -------------------- + // String.fromCharCode.apply(null, array) is the fastest, see + // see http://jsperf.com/converting-a-uint8array-to-a-string/2 + // but the stack is limited (and we can get huge arrays !). + // + // result += String.fromCharCode(array[i]); generate too many strings ! + // + // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 + // TODO : we now have workers that split the work. Do we still need that ? + var chunk = 65536, + type = exports.getTypeOf(array), + canUseApply = true; + if (type === "uint8array") { + canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; + } else if (type === "nodebuffer") { + canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; + } + + if (canUseApply) { + while (chunk > 1) { + try { + return arrayToStringHelper.stringifyByChunk(array, type, chunk); + } catch (e) { + chunk = Math.floor(chunk / 2); + } + } + } + + // no apply or chunk error : slow and painful algorithm + // default browser on android 4.* + return arrayToStringHelper.stringifyByChar(array); +} + +exports.applyFromCharCode = arrayLikeToString; + + +/** + * Copy the data from an array-like to an other array-like. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. + */ +function arrayLikeToArrayLike(arrayFrom, arrayTo) { + for (var i = 0; i < arrayFrom.length; i++) { + arrayTo[i] = arrayFrom[i]; + } + return arrayTo; +} + +// a matrix containing functions to transform everything into everything. +var transform = {}; + +// string to ? +transform["string"] = { + "string": identity, + "array": function(input) { + return stringToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["string"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return stringToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": function(input) { + return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); + } +}; + +// array to ? +transform["array"] = { + "string": arrayLikeToString, + "array": identity, + "arraybuffer": function(input) { + return (new Uint8Array(input)).buffer; + }, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// arraybuffer to ? +transform["arraybuffer"] = { + "string": function(input) { + return arrayLikeToString(new Uint8Array(input)); + }, + "array": function(input) { + return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); + }, + "arraybuffer": identity, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(new Uint8Array(input)); + } +}; + +// uint8array to ? +transform["uint8array"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return input.buffer; + }, + "uint8array": identity, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// nodebuffer to ? +transform["nodebuffer"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["nodebuffer"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return arrayLikeToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": identity +}; + +/** + * Transform an input into any type. + * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. + * If no output type is specified, the unmodified input will be returned. + * @param {String} outputType the output type. + * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. + * @throws {Error} an Error if the browser doesn't support the requested output type. + */ +exports.transformTo = function(outputType, input) { + if (!input) { + // undefined, null, etc + // an empty string won't harm. + input = ""; + } + if (!outputType) { + return input; + } + exports.checkSupport(outputType); + var inputType = exports.getTypeOf(input); + var result = transform[inputType][outputType](input); + return result; +}; + +/** + * Return the type of the input. + * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. + * @param {Object} input the input to identify. + * @return {String} the (lowercase) type of the input. + */ +exports.getTypeOf = function(input) { + if (typeof input === "string") { + return "string"; + } + if (Object.prototype.toString.call(input) === "[object Array]") { + return "array"; + } + if (support.nodebuffer && nodejsUtils.isBuffer(input)) { + return "nodebuffer"; + } + if (support.uint8array && input instanceof Uint8Array) { + return "uint8array"; + } + if (support.arraybuffer && input instanceof ArrayBuffer) { + return "arraybuffer"; + } +}; + +/** + * Throw an exception if the type is not supported. + * @param {String} type the type to check. + * @throws {Error} an Error if the browser doesn't support the requested type. + */ +exports.checkSupport = function(type) { + var supported = support[type.toLowerCase()]; + if (!supported) { + throw new Error(type + " is not supported by this platform"); + } +}; + +exports.MAX_VALUE_16BITS = 65535; +exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 + +/** + * Prettify a string read as binary. + * @param {string} str the string to prettify. + * @return {string} a pretty string. + */ +exports.pretty = function(str) { + var res = '', + code, i; + for (i = 0; i < (str || "").length; i++) { + code = str.charCodeAt(i); + res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); + } + return res; +}; + +/** + * Defer the call of a function. + * @param {Function} callback the function to call asynchronously. + * @param {Array} args the arguments to give to the callback. + */ +exports.delay = function(callback, args, self) { + setImmediate(function () { + callback.apply(self || null, args || []); + }); +}; + +/** + * Extends a prototype with an other, without calling a constructor with + * side effects. Inspired by nodejs' `utils.inherits` + * @param {Function} ctor the constructor to augment + * @param {Function} superCtor the parent constructor to use + */ +exports.inherits = function (ctor, superCtor) { + var Obj = function() {}; + Obj.prototype = superCtor.prototype; + ctor.prototype = new Obj(); +}; + +/** + * Merge the objects passed as parameters into a new one. + * @private + * @param {...Object} var_args All objects to merge. + * @return {Object} a new object with the data of the others. + */ +exports.extend = function() { + var result = {}, i, attr; + for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers + for (attr in arguments[i]) { + if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { + result[attr] = arguments[i][attr]; + } + } + } + return result; +}; + +/** + * Transform arbitrary content into a Promise. + * @param {String} name a name for the content being processed. + * @param {Object} inputData the content to process. + * @param {Boolean} isBinary true if the content is not an unicode string + * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. + * @param {Boolean} isBase64 true if the string content is encoded with base64. + * @return {Promise} a promise in a format usable by JSZip. + */ +exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { + + // if inputData is already a promise, this flatten it. + var promise = external.Promise.resolve(inputData).then(function(data) { + + + var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); + + if (isBlob && typeof FileReader !== "undefined") { + return new external.Promise(function (resolve, reject) { + var reader = new FileReader(); + + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e.target.error); + }; + reader.readAsArrayBuffer(data); + }); + } else { + return data; + } + }); + + return promise.then(function(data) { + var dataType = exports.getTypeOf(data); + + if (!dataType) { + return external.Promise.reject( + new Error("Can't read the data of '" + name + "'. Is it " + + "in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") + ); + } + // special case : it's way easier to work with Uint8Array than with ArrayBuffer + if (dataType === "arraybuffer") { + data = exports.transformTo("uint8array", data); + } else if (dataType === "string") { + if (isBase64) { + data = base64.decode(data); + } + else if (isBinary) { + // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask + if (isOptimizedBinaryString !== true) { + // this is a string, not in a base64 format. + // Be sure that this is a correct "binary string" + data = string2binary(data); + } + } + } + return data; + }); +}; + +},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"core-js/library/fn/set-immediate":36}],33:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var sig = require('./signature'); +var ZipEntry = require('./zipEntry'); +var utf8 = require('./utf8'); +var support = require('./support'); +// class ZipEntries {{{ +/** + * All the entries in the zip file. + * @constructor + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntries(loadOptions) { + this.files = []; + this.loadOptions = loadOptions; +} +ZipEntries.prototype = { + /** + * Check that the reader is on the specified signature. + * @param {string} expectedSignature the expected signature. + * @throws {Error} if it is an other signature. + */ + checkSignature: function(expectedSignature) { + if (!this.reader.readAndCheckSignature(expectedSignature)) { + this.reader.index -= 4; + var signature = this.reader.readString(4); + throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); + } + }, + /** + * Check if the given signature is at the given index. + * @param {number} askedIndex the index to check. + * @param {string} expectedSignature the signature to expect. + * @return {boolean} true if the signature is here, false otherwise. + */ + isSignature: function(askedIndex, expectedSignature) { + var currentIndex = this.reader.index; + this.reader.setIndex(askedIndex); + var signature = this.reader.readString(4); + var result = signature === expectedSignature; + this.reader.setIndex(currentIndex); + return result; + }, + /** + * Read the end of the central directory. + */ + readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2); + this.diskWithCentralDirStart = this.reader.readInt(2); + this.centralDirRecordsOnThisDisk = this.reader.readInt(2); + this.centralDirRecords = this.reader.readInt(2); + this.centralDirSize = this.reader.readInt(4); + this.centralDirOffset = this.reader.readInt(4); + + this.zipCommentLength = this.reader.readInt(2); + // warning : the encoding depends of the system locale + // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. + // On a windows machine, this field is encoded with the localized windows code page. + var zipComment = this.reader.readData(this.zipCommentLength); + var decodeParamType = support.uint8array ? "uint8array" : "array"; + // To get consistent behavior with the generation part, we will assume that + // this is utf8 encoded unless specified otherwise. + var decodeContent = utils.transformTo(decodeParamType, zipComment); + this.zipComment = this.loadOptions.decodeFileName(decodeContent); + }, + /** + * Read the end of the Zip 64 central directory. + * Not merged with the method readEndOfCentral : + * The end of central can coexist with its Zip64 brother, + * I don't want to read the wrong number of bytes ! + */ + readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8); + this.reader.skip(4); + // this.versionMadeBy = this.reader.readString(2); + // this.versionNeeded = this.reader.readInt(2); + this.diskNumber = this.reader.readInt(4); + this.diskWithCentralDirStart = this.reader.readInt(4); + this.centralDirRecordsOnThisDisk = this.reader.readInt(8); + this.centralDirRecords = this.reader.readInt(8); + this.centralDirSize = this.reader.readInt(8); + this.centralDirOffset = this.reader.readInt(8); + + this.zip64ExtensibleData = {}; + var extraDataSize = this.zip64EndOfCentralSize - 44, + index = 0, + extraFieldId, + extraFieldLength, + extraFieldValue; + while (index < extraDataSize) { + extraFieldId = this.reader.readInt(2); + extraFieldLength = this.reader.readInt(4); + extraFieldValue = this.reader.readData(extraFieldLength); + this.zip64ExtensibleData[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Read the end of the Zip 64 central directory locator. + */ + readBlockZip64EndOfCentralLocator: function() { + this.diskWithZip64CentralDirStart = this.reader.readInt(4); + this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); + this.disksCount = this.reader.readInt(4); + if (this.disksCount > 1) { + throw new Error("Multi-volumes zip are not supported"); + } + }, + /** + * Read the local files, based on the offset read in the central part. + */ + readLocalFiles: function() { + var i, file; + for (i = 0; i < this.files.length; i++) { + file = this.files[i]; + this.reader.setIndex(file.localHeaderOffset); + this.checkSignature(sig.LOCAL_FILE_HEADER); + file.readLocalPart(this.reader); + file.handleUTF8(); + file.processAttributes(); + } + }, + /** + * Read the central directory. + */ + readCentralDir: function() { + var file; + + this.reader.setIndex(this.centralDirOffset); + while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) { + file = new ZipEntry({ + zip64: this.zip64 + }, this.loadOptions); + file.readCentralPart(this.reader); + this.files.push(file); + } + + if (this.centralDirRecords !== this.files.length) { + if (this.centralDirRecords !== 0 && this.files.length === 0) { + // We expected some records but couldn't find ANY. + // This is really suspicious, as if something went wrong. + throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); + } else { + // We found some records but not all. + // Something is wrong but we got something for the user: no error here. + // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length); + } + } + }, + /** + * Read the end of central directory. + */ + readEndOfCentral: function() { + var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); + if (offset < 0) { + // Check if the content is a truncated zip or complete garbage. + // A "LOCAL_FILE_HEADER" is not required at the beginning (auto + // extractible zip for example) but it can give a good hint. + // If an ajax request was used without responseType, we will also + // get unreadable data. + var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER); + + if (isGarbage) { + throw new Error("Can't find end of central directory : is this a zip file ? " + + "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"); + } else { + throw new Error("Corrupted zip: can't find end of central directory"); + } + + } + this.reader.setIndex(offset); + var endOfCentralDirOffset = offset; + this.checkSignature(sig.CENTRAL_DIRECTORY_END); + this.readBlockEndOfCentral(); + + + /* extract from the zip spec : + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + */ + if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { + this.zip64 = true; + + /* + Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from + the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents + all numbers as 64-bit double precision IEEE 754 floating point numbers. + So, we have 53bits for integers and bitwise operations treat everything as 32bits. + see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators + and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 + */ + + // should look for a zip64 EOCD locator + offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + if (offset < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + this.readBlockZip64EndOfCentralLocator(); + + // now the zip64 EOCD record + if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) { + // console.warn("ZIP64 end of central directory not where expected."); + this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + if (this.relativeOffsetEndOfZip64CentralDir < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); + } + } + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + this.readBlockZip64EndOfCentral(); + } + + var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize; + if (this.zip64) { + expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator + expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize; + } + + var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset; + + if (extraBytes > 0) { + // console.warn(extraBytes, "extra bytes at beginning or within zipfile"); + if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) { + // The offsets seem wrong, but we have something at the specified offset. + // So… we keep it. + } else { + // the offset is wrong, update the "zero" of the reader + // this happens if data has been prepended (crx files for example) + this.reader.zero = extraBytes; + } + } else if (extraBytes < 0) { + throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes."); + } + }, + prepareReader: function(data) { + this.reader = readerFor(data); + }, + /** + * Read a zip file and create ZipEntries. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. + */ + load: function(data) { + this.prepareReader(data); + this.readEndOfCentral(); + this.readCentralDir(); + this.readLocalFiles(); + } +}; +// }}} end of ZipEntries +module.exports = ZipEntries; + +},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var CompressedObject = require('./compressedObject'); +var crc32fn = require('./crc32'); +var utf8 = require('./utf8'); +var compressions = require('./compressions'); +var support = require('./support'); + +var MADE_BY_DOS = 0x00; +var MADE_BY_UNIX = 0x03; + +/** + * Find a compression registered in JSZip. + * @param {string} compressionMethod the method magic to find. + * @return {Object|null} the JSZip compression object, null if none found. + */ +var findCompression = function(compressionMethod) { + for (var method in compressions) { + if (!compressions.hasOwnProperty(method)) { + continue; + } + if (compressions[method].magic === compressionMethod) { + return compressions[method]; + } + } + return null; +}; + +// class ZipEntry {{{ +/** + * An entry in the zip file. + * @constructor + * @param {Object} options Options of the current file. + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntry(options, loadOptions) { + this.options = options; + this.loadOptions = loadOptions; +} +ZipEntry.prototype = { + /** + * say if the file is encrypted. + * @return {boolean} true if the file is encrypted, false otherwise. + */ + isEncrypted: function() { + // bit 1 is set + return (this.bitFlag & 0x0001) === 0x0001; + }, + /** + * say if the file has utf-8 filename/comment. + * @return {boolean} true if the filename/comment is in utf-8, false otherwise. + */ + useUTF8: function() { + // bit 11 is set + return (this.bitFlag & 0x0800) === 0x0800; + }, + /** + * Read the local part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readLocalPart: function(reader) { + var compression, localExtraFieldsLength; + + // we already know everything from the central dir ! + // If the central dir data are false, we are doomed. + // On the bright side, the local part is scary : zip64, data descriptors, both, etc. + // The less data we get here, the more reliable this should be. + // Let's skip the whole header and dash to the data ! + reader.skip(22); + // in some zip created on windows, the filename stored in the central dir contains \ instead of /. + // Strangely, the filename here is OK. + // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes + // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... + // Search "unzip mismatching "local" filename continuing with "central" filename version" on + // the internet. + // + // I think I see the logic here : the central directory is used to display + // content and the local directory is used to extract the files. Mixing / and \ + // may be used to display \ to windows users and use / when extracting the files. + // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 + this.fileNameLength = reader.readInt(2); + localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir + // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding. + this.fileName = reader.readData(this.fileNameLength); + reader.skip(localExtraFieldsLength); + + if (this.compressedSize === -1 || this.uncompressedSize === -1) { + throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)"); + } + + compression = findCompression(this.compressionMethod); + if (compression === null) { // no compression found + throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")"); + } + this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize)); + }, + + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readCentralPart: function(reader) { + this.versionMadeBy = reader.readInt(2); + reader.skip(2); + // this.versionNeeded = reader.readInt(2); + this.bitFlag = reader.readInt(2); + this.compressionMethod = reader.readString(2); + this.date = reader.readDate(); + this.crc32 = reader.readInt(4); + this.compressedSize = reader.readInt(4); + this.uncompressedSize = reader.readInt(4); + var fileNameLength = reader.readInt(2); + this.extraFieldsLength = reader.readInt(2); + this.fileCommentLength = reader.readInt(2); + this.diskNumberStart = reader.readInt(2); + this.internalFileAttributes = reader.readInt(2); + this.externalFileAttributes = reader.readInt(4); + this.localHeaderOffset = reader.readInt(4); + + if (this.isEncrypted()) { + throw new Error("Encrypted zip are not supported"); + } + + // will be read in the local part, see the comments there + reader.skip(fileNameLength); + this.readExtraFields(reader); + this.parseZIP64ExtraField(reader); + this.fileComment = reader.readData(this.fileCommentLength); + }, + + /** + * Parse the external file attributes and get the unix/dos permissions. + */ + processAttributes: function () { + this.unixPermissions = null; + this.dosPermissions = null; + var madeBy = this.versionMadeBy >> 8; + + // Check if we have the DOS directory flag set. + // We look for it in the DOS and UNIX permissions + // but some unknown platform could set it as a compatibility flag. + this.dir = this.externalFileAttributes & 0x0010 ? true : false; + + if(madeBy === MADE_BY_DOS) { + // first 6 bits (0 to 5) + this.dosPermissions = this.externalFileAttributes & 0x3F; + } + + if(madeBy === MADE_BY_UNIX) { + this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; + // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); + } + + // fail safe : if the name ends with a / it probably means a folder + if (!this.dir && this.fileNameStr.slice(-1) === '/') { + this.dir = true; + } + }, + + /** + * Parse the ZIP64 extra field and merge the info in the current ZipEntry. + * @param {DataReader} reader the reader to use. + */ + parseZIP64ExtraField: function(reader) { + + if (!this.extraFields[0x0001]) { + return; + } + + // should be something, preparing the extra reader + var extraReader = readerFor(this.extraFields[0x0001].value); + + // I really hope that these 64bits integer can fit in 32 bits integer, because js + // won't let us have more. + if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { + this.uncompressedSize = extraReader.readInt(8); + } + if (this.compressedSize === utils.MAX_VALUE_32BITS) { + this.compressedSize = extraReader.readInt(8); + } + if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { + this.localHeaderOffset = extraReader.readInt(8); + } + if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { + this.diskNumberStart = extraReader.readInt(4); + } + }, + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readExtraFields: function(reader) { + var end = reader.index + this.extraFieldsLength, + extraFieldId, + extraFieldLength, + extraFieldValue; + + if (!this.extraFields) { + this.extraFields = {}; + } + + while (reader.index < end) { + extraFieldId = reader.readInt(2); + extraFieldLength = reader.readInt(2); + extraFieldValue = reader.readData(extraFieldLength); + + this.extraFields[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Apply an UTF8 transformation if needed. + */ + handleUTF8: function() { + var decodeParamType = support.uint8array ? "uint8array" : "array"; + if (this.useUTF8()) { + this.fileNameStr = utf8.utf8decode(this.fileName); + this.fileCommentStr = utf8.utf8decode(this.fileComment); + } else { + var upath = this.findExtraFieldUnicodePath(); + if (upath !== null) { + this.fileNameStr = upath; + } else { + // ASCII text or unsupported code page + var fileNameByteArray = utils.transformTo(decodeParamType, this.fileName); + this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray); + } + + var ucomment = this.findExtraFieldUnicodeComment(); + if (ucomment !== null) { + this.fileCommentStr = ucomment; + } else { + // ASCII text or unsupported code page + var commentByteArray = utils.transformTo(decodeParamType, this.fileComment); + this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray); + } + } + }, + + /** + * Find the unicode path declared in the extra field, if any. + * @return {String} the unicode path, null otherwise. + */ + findExtraFieldUnicodePath: function() { + var upathField = this.extraFields[0x7075]; + if (upathField) { + var extraReader = readerFor(upathField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the filename changed, this field is out of date. + if (crc32fn(this.fileName) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(upathField.length - 5)); + } + return null; + }, + + /** + * Find the unicode comment declared in the extra field, if any. + * @return {String} the unicode comment, null otherwise. + */ + findExtraFieldUnicodeComment: function() { + var ucommentField = this.extraFields[0x6375]; + if (ucommentField) { + var extraReader = readerFor(ucommentField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the comment changed, this field is out of date. + if (crc32fn(this.fileComment) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(ucommentField.length - 5)); + } + return null; + } +}; +module.exports = ZipEntry; + +},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(require,module,exports){ +'use strict'; + +var StreamHelper = require('./stream/StreamHelper'); +var DataWorker = require('./stream/DataWorker'); +var utf8 = require('./utf8'); +var CompressedObject = require('./compressedObject'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * A simple object representing a file in the zip file. + * @constructor + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data + * @param {Object} options the options of the file + */ +var ZipObject = function(name, data, options) { + this.name = name; + this.dir = options.dir; + this.date = options.date; + this.comment = options.comment; + this.unixPermissions = options.unixPermissions; + this.dosPermissions = options.dosPermissions; + + this._data = data; + this._dataBinary = options.binary; + // keep only the compression + this.options = { + compression : options.compression, + compressionOptions : options.compressionOptions + }; +}; + +ZipObject.prototype = { + /** + * Create an internal stream for the content of this object. + * @param {String} type the type of each chunk. + * @return StreamHelper the stream. + */ + internalStream: function (type) { + var result = null, outputType = "string"; + try { + if (!type) { + throw new Error("No output type specified."); + } + outputType = type.toLowerCase(); + var askUnicodeString = outputType === "string" || outputType === "text"; + if (outputType === "binarystring" || outputType === "text") { + outputType = "string"; + } + result = this._decompressWorker(); + + var isUnicodeString = !this._dataBinary; + + if (isUnicodeString && !askUnicodeString) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + if (!isUnicodeString && askUnicodeString) { + result = result.pipe(new utf8.Utf8DecodeWorker()); + } + } catch (e) { + result = new GenericWorker("error"); + result.error(e); + } + + return new StreamHelper(result, outputType, ""); + }, + + /** + * Prepare the content in the asked type. + * @param {String} type the type of the result. + * @param {Function} onUpdate a function to call on each internal update. + * @return Promise the promise of the result. + */ + async: function (type, onUpdate) { + return this.internalStream(type).accumulate(onUpdate); + }, + + /** + * Prepare the content as a nodejs stream. + * @param {String} type the type of each chunk. + * @param {Function} onUpdate a function to call on each internal update. + * @return Stream the stream. + */ + nodeStream: function (type, onUpdate) { + return this.internalStream(type || "nodebuffer").toNodejsStream(onUpdate); + }, + + /** + * Return a worker for the compressed content. + * @private + * @param {Object} compression the compression object to use. + * @param {Object} compressionOptions the options to use when compressing. + * @return Worker the worker. + */ + _compressWorker: function (compression, compressionOptions) { + if ( + this._data instanceof CompressedObject && + this._data.compression.magic === compression.magic + ) { + return this._data.getCompressedWorker(); + } else { + var result = this._decompressWorker(); + if(!this._dataBinary) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + return CompressedObject.createWorkerFrom(result, compression, compressionOptions); + } + }, + /** + * Return a worker for the decompressed content. + * @private + * @return Worker the worker. + */ + _decompressWorker : function () { + if (this._data instanceof CompressedObject) { + return this._data.getContentWorker(); + } else if (this._data instanceof GenericWorker) { + return this._data; + } else { + return new DataWorker(this._data); + } + } +}; + +var removedMethods = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"]; +var removedFn = function () { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); +}; + +for(var i = 0; i < removedMethods.length; i++) { + ZipObject.prototype[removedMethods[i]] = removedFn; +} +module.exports = ZipObject; + +},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(require,module,exports){ +require('../modules/web.immediate'); +module.exports = require('../modules/_core').setImmediate; +},{"../modules/_core":40,"../modules/web.immediate":56}],37:[function(require,module,exports){ +module.exports = function(it){ + if(typeof it != 'function')throw TypeError(it + ' is not a function!'); + return it; +}; +},{}],38:[function(require,module,exports){ +var isObject = require('./_is-object'); +module.exports = function(it){ + if(!isObject(it))throw TypeError(it + ' is not an object!'); + return it; +}; +},{"./_is-object":51}],39:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = function(it){ + return toString.call(it).slice(8, -1); +}; +},{}],40:[function(require,module,exports){ +var core = module.exports = {version: '2.3.0'}; +if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef +},{}],41:[function(require,module,exports){ +// optional / simple context binding +var aFunction = require('./_a-function'); +module.exports = function(fn, that, length){ + aFunction(fn); + if(that === undefined)return fn; + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; +}; +},{"./_a-function":37}],42:[function(require,module,exports){ +// Thank's IE8 for his funny defineProperty +module.exports = !require('./_fails')(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_fails":45}],43:[function(require,module,exports){ +var isObject = require('./_is-object') + , document = require('./_global').document + // in old IE typeof document.createElement is 'object' + , is = isObject(document) && isObject(document.createElement); +module.exports = function(it){ + return is ? document.createElement(it) : {}; +}; +},{"./_global":46,"./_is-object":51}],44:[function(require,module,exports){ +var global = require('./_global') + , core = require('./_core') + , ctx = require('./_ctx') + , hide = require('./_hide') + , PROTOTYPE = 'prototype'; + +var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , IS_WRAP = type & $export.W + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] + , key, own, out; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if(own && key in exports)continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function(C){ + var F = function(a, b, c){ + if(this instanceof C){ + switch(arguments.length){ + case 0: return new C; + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if(IS_PROTO){ + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); + } + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; +},{"./_core":40,"./_ctx":41,"./_global":46,"./_hide":47}],45:[function(require,module,exports){ +module.exports = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } +}; +},{}],46:[function(require,module,exports){ +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); +if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef +},{}],47:[function(require,module,exports){ +var dP = require('./_object-dp') + , createDesc = require('./_property-desc'); +module.exports = require('./_descriptors') ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); +} : function(object, key, value){ + object[key] = value; + return object; +}; +},{"./_descriptors":42,"./_object-dp":52,"./_property-desc":53}],48:[function(require,module,exports){ +module.exports = require('./_global').document && document.documentElement; +},{"./_global":46}],49:[function(require,module,exports){ +module.exports = !require('./_descriptors') && !require('./_fails')(function(){ + return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_descriptors":42,"./_dom-create":43,"./_fails":45}],50:[function(require,module,exports){ +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function(fn, args, that){ + var un = that === undefined; + switch(args.length){ + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; +},{}],51:[function(require,module,exports){ +module.exports = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; +},{}],52:[function(require,module,exports){ +var anObject = require('./_an-object') + , IE8_DOM_DEFINE = require('./_ie8-dom-define') + , toPrimitive = require('./_to-primitive') + , dP = Object.defineProperty; + +exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){ + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if(IE8_DOM_DEFINE)try { + return dP(O, P, Attributes); + } catch(e){ /* empty */ } + if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); + if('value' in Attributes)O[P] = Attributes.value; + return O; +}; +},{"./_an-object":38,"./_descriptors":42,"./_ie8-dom-define":49,"./_to-primitive":55}],53:[function(require,module,exports){ +module.exports = function(bitmap, value){ + return { + enumerable : !(bitmap & 1), + configurable: !(bitmap & 2), + writable : !(bitmap & 4), + value : value + }; +}; +},{}],54:[function(require,module,exports){ +var ctx = require('./_ctx') + , invoke = require('./_invoke') + , html = require('./_html') + , cel = require('./_dom-create') + , global = require('./_global') + , process = global.process + , setTask = global.setImmediate + , clearTask = global.clearImmediate + , MessageChannel = global.MessageChannel + , counter = 0 + , queue = {} + , ONREADYSTATECHANGE = 'onreadystatechange' + , defer, channel, port; +var run = function(){ + var id = +this; + if(queue.hasOwnProperty(id)){ + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function(event){ + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if(!setTask || !clearTask){ + setTask = function setImmediate(fn){ + var args = [], i = 1; + while(arguments.length > i)args.push(arguments[i++]); + queue[++counter] = function(){ + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id){ + delete queue[id]; + }; + // Node.js 0.8- + if(require('./_cof')(process) == 'process'){ + defer = function(id){ + process.nextTick(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if(MessageChannel){ + channel = new MessageChannel; + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ + defer = function(id){ + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if(ONREADYSTATECHANGE in cel('script')){ + defer = function(id){ + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function(id){ + setTimeout(ctx(run, id, 1), 0); + }; + } +} +module.exports = { + set: setTask, + clear: clearTask +}; +},{"./_cof":39,"./_ctx":41,"./_dom-create":43,"./_global":46,"./_html":48,"./_invoke":50}],55:[function(require,module,exports){ +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = require('./_is-object'); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function(it, S){ + if(!isObject(it))return it; + var fn, val; + if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; + if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + throw TypeError("Can't convert object to primitive value"); +}; +},{"./_is-object":51}],56:[function(require,module,exports){ +var $export = require('./_export') + , $task = require('./_task'); +$export($export.G + $export.B, { + setImmediate: $task.set, + clearImmediate: $task.clear +}); +},{"./_export":44,"./_task":54}],57:[function(require,module,exports){ +(function (global){ +'use strict'; +var Mutation = global.MutationObserver || global.WebKitMutationObserver; + +var scheduleDrain; + +{ + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + scheduleDrain = function () { + element.data = (called = ++called % 2); + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + + // Create a + + - - +
              - -
              - - - - - - - -
              - - -
              -

              ACF (JDA) 0.5.0-SNAPSHOT API

              -
              -
              - - - - - - - - - - - - - - - - -
              Packages 
              PackageDescription
              co.aikar.commands 
              co.aikar.commands.annotation 
              -
              - -
              - - - - - - - -
              - - -

              Copyright © 2019. All rights reserved.

              +

              index.html

              +
              diff --git a/docs/acf-jda/overview-tree.html b/docs/acf-jda/overview-tree.html index 47087d57..73377602 100644 --- a/docs/acf-jda/overview-tree.html +++ b/docs/acf-jda/overview-tree.html @@ -1,12 +1,21 @@ - + - Class Hierarchy (ACF (JDA) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
              + +
              +

              Hierarchy For All Packages

              Package Hierarchies: @@ -77,84 +101,93 @@
      +

      Class Hierarchy

      +
      +

      Interface Hierarchy

      +
      +

      Annotation Type Hierarchy

      +
      +
      + diff --git a/docs/acf-jda/package-search-index.js b/docs/acf-jda/package-search-index.js new file mode 100644 index 00000000..fad4132d --- /dev/null +++ b/docs/acf-jda/package-search-index.js @@ -0,0 +1 @@ +packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"co.aikar.commands"},{"l":"co.aikar.commands.annotation"}] \ No newline at end of file diff --git a/docs/acf-jda/package-search-index.zip b/docs/acf-jda/package-search-index.zip new file mode 100644 index 00000000..44f4c343 Binary files /dev/null and b/docs/acf-jda/package-search-index.zip differ diff --git a/docs/acf-jda/resources/glass.png b/docs/acf-jda/resources/glass.png new file mode 100644 index 00000000..a7f591f4 Binary files /dev/null and b/docs/acf-jda/resources/glass.png differ diff --git a/docs/acf-jda/resources/x.png b/docs/acf-jda/resources/x.png new file mode 100644 index 00000000..30548a75 Binary files /dev/null and b/docs/acf-jda/resources/x.png differ diff --git a/docs/acf-jda/script.js b/docs/acf-jda/script.js index b3463569..0eaaf535 100644 --- a/docs/acf-jda/script.js +++ b/docs/acf-jda/script.js @@ -1,9 +1,114 @@ -function show(type) -{ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var moduleSearchIndex; +var packageSearchIndex; +var typeSearchIndex; +var memberSearchIndex; +var tagSearchIndex; +function loadScripts(doc, tag) { + createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); + if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || + window.navigator.userAgent.indexOf('Edge/') > 0) { + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); + } + createElem(doc, tag, 'search.js'); + + $.get(pathtoroot + "module-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + moduleSearchIndex = JSON.parse(zip.file("module-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "package-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + packageSearchIndex = JSON.parse(zip.file("package-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "type-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + typeSearchIndex = JSON.parse(zip.file("type-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "member-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + memberSearchIndex = JSON.parse(zip.file("member-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "tag-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + tagSearchIndex = JSON.parse(zip.file("tag-search-index.json").asText()); + }); + }); + if (!moduleSearchIndex) { + createElem(doc, tag, 'module-search-index.js'); + } + if (!packageSearchIndex) { + createElem(doc, tag, 'package-search-index.js'); + } + if (!typeSearchIndex) { + createElem(doc, tag, 'type-search-index.js'); + } + if (!memberSearchIndex) { + createElem(doc, tag, 'member-search-index.js'); + } + if (!tagSearchIndex) { + createElem(doc, tag, 'tag-search-index.js'); + } + $(window).resize(function() { + $('.navPadding').css('padding-top', $('.fixedNav').css("height")); + }); +} + +function createElem(doc, tag, path) { + var script = doc.createElement(tag); + var scriptElement = doc.getElementsByTagName(tag)[0]; + script.src = pathtoroot + path; + scriptElement.parentNode.insertBefore(script, scriptElement); +} + +function show(type) { count = 0; - for (var key in methods) { + for (var key in data) { var row = document.getElementById(key); - if ((methods[key] & type) != 0) { + if ((data[key] & type) !== 0) { row.style.display = ''; row.className = (count++ % 2) ? rowColor : altColor; } @@ -13,8 +118,7 @@ function show(type) updateTabs(type); } -function updateTabs(type) -{ +function updateTabs(type) { for (var value in tabs) { var sNode = document.getElementById(tabs[value][0]); var spanNode = sNode.firstChild; @@ -28,3 +132,8 @@ function updateTabs(type) } } } + +function updateModuleFrame(pFrame, cFrame) { + top.packageFrame.location = pFrame; + top.classFrame.location = cFrame; +} diff --git a/docs/acf-jda/search.js b/docs/acf-jda/search.js new file mode 100644 index 00000000..b773531b --- /dev/null +++ b/docs/acf-jda/search.js @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var noResult = {l: "No results found"}; +var catModules = "Modules"; +var catPackages = "Packages"; +var catTypes = "Types"; +var catMembers = "Members"; +var catSearchTags = "SearchTags"; +var highlight = "$&"; +var camelCaseRegexp = ""; +var secondaryMatcher = ""; +function getHighlightedText(item) { + var ccMatcher = new RegExp(camelCaseRegexp); + var label = item.replace(ccMatcher, highlight); + if (label === item) { + label = item.replace(secondaryMatcher, highlight); + } + return label; +} +function getURLPrefix(ui) { + var urlPrefix=""; + if (useModuleDirectories) { + var slash = "/"; + if (ui.item.category === catModules) { + return ui.item.l + slash; + } else if (ui.item.category === catPackages && ui.item.m) { + return ui.item.m + slash; + } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { + $.each(packageSearchIndex, function(index, item) { + if (ui.item.p == item.l) { + urlPrefix = item.m + slash; + } + }); + return urlPrefix; + } else { + return urlPrefix; + } + } + return urlPrefix; +} +var watermark = 'Search'; +$(function() { + $("#search").val(''); + $("#search").prop("disabled", false); + $("#reset").prop("disabled", false); + $("#search").val(watermark).addClass('watermark'); + $("#search").blur(function() { + if ($(this).val().length == 0) { + $(this).val(watermark).addClass('watermark'); + } + }); + $("#search").on('click keydown', function() { + if ($(this).val() == watermark) { + $(this).val('').removeClass('watermark'); + } + }); + $("#reset").click(function() { + $("#search").val(''); + $("#search").focus(); + }); + $("#search").focus(); + $("#search")[0].setSelectionRange(0, 0); +}); +$.widget("custom.catcomplete", $.ui.autocomplete, { + _create: function() { + this._super(); + this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)"); + }, + _renderMenu: function(ul, items) { + var rMenu = this, + currentCategory = ""; + rMenu.menu.bindings = $(); + $.each(items, function(index, item) { + var li; + if (item.l !== noResult.l && item.category !== currentCategory) { + ul.append("
    • " + item.category + "
    • "); + currentCategory = item.category; + } + li = rMenu._renderItemData(ul, item); + if (item.category) { + li.attr("aria-label", item.category + " : " + item.l); + li.attr("class", "resultItem"); + } else { + li.attr("aria-label", item.l); + li.attr("class", "resultItem"); + } + }); + }, + _renderItem: function(ul, item) { + var label = ""; + if (item.category === catModules) { + label = getHighlightedText(item.l); + } else if (item.category === catPackages) { + label = (item.m) + ? getHighlightedText(item.m + "/" + item.l) + : getHighlightedText(item.l); + } else if (item.category === catTypes) { + label = (item.p) + ? getHighlightedText(item.p + "." + item.l) + : getHighlightedText(item.l); + } else if (item.category === catMembers) { + label = getHighlightedText(item.p + "." + (item.c + "." + item.l)); + } else if (item.category === catSearchTags) { + label = getHighlightedText(item.l); + } else { + label = item.l; + } + var li = $("
    • ").appendTo(ul); + var div = $("
      ").appendTo(li); + if (item.category === catSearchTags) { + if (item.d) { + div.html(label + " (" + item.h + ")
      " + + item.d + "
      "); + } else { + div.html(label + " (" + item.h + ")"); + } + } else { + div.html(label); + } + return li; + } +}); +$(function() { + $("#search").catcomplete({ + minLength: 1, + delay: 100, + source: function(request, response) { + var result = new Array(); + var presult = new Array(); + var tresult = new Array(); + var mresult = new Array(); + var tgresult = new Array(); + var secondaryresult = new Array(); + var displayCount = 0; + var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i"); + camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)"); + var camelCaseMatcher = new RegExp("^" + camelCaseRegexp); + secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); + + // Return the nested innermost name from the specified object + function nestedName(e) { + return e.l.substring(e.l.lastIndexOf(".") + 1); + } + + function concatResults(a1, a2) { + a1 = a1.concat(a2); + a2.length = 0; + return a1; + } + + if (moduleSearchIndex) { + var mdleCount = 0; + $.each(moduleSearchIndex, function(index, item) { + item.category = catModules; + if (exactMatcher.test(item.l)) { + result.push(item); + mdleCount++; + } else if (camelCaseMatcher.test(item.l)) { + result.push(item); + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + displayCount = mdleCount; + result = concatResults(result, secondaryresult); + } + if (packageSearchIndex) { + var pCount = 0; + var pkg = ""; + $.each(packageSearchIndex, function(index, item) { + item.category = catPackages; + pkg = (item.m) + ? (item.m + "/" + item.l) + : item.l; + if (exactMatcher.test(item.l)) { + presult.push(item); + pCount++; + } else if (camelCaseMatcher.test(pkg)) { + presult.push(item); + } else if (secondaryMatcher.test(pkg)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(presult, secondaryresult)); + displayCount = (pCount > displayCount) ? pCount : displayCount; + } + if (typeSearchIndex) { + var tCount = 0; + $.each(typeSearchIndex, function(index, item) { + item.category = catTypes; + var s = nestedName(item); + if (exactMatcher.test(s)) { + tresult.push(item); + tCount++; + } else if (camelCaseMatcher.test(s)) { + tresult.push(item); + } else if (secondaryMatcher.test(item.p + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tresult, secondaryresult)); + displayCount = (tCount > displayCount) ? tCount : displayCount; + } + if (memberSearchIndex) { + var mCount = 0; + $.each(memberSearchIndex, function(index, item) { + item.category = catMembers; + var s = nestedName(item); + if (exactMatcher.test(s)) { + mresult.push(item); + mCount++; + } else if (camelCaseMatcher.test(s)) { + mresult.push(item); + } else if (secondaryMatcher.test(item.c + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(mresult, secondaryresult)); + displayCount = (mCount > displayCount) ? mCount : displayCount; + } + if (tagSearchIndex) { + var tgCount = 0; + $.each(tagSearchIndex, function(index, item) { + item.category = catSearchTags; + if (exactMatcher.test(item.l)) { + tgresult.push(item); + tgCount++; + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tgresult, secondaryresult)); + displayCount = (tgCount > displayCount) ? tgCount : displayCount; + } + displayCount = (displayCount > 500) ? displayCount : 500; + var counter = function() { + var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0}; + var f = function(item) { + count[item.category] += 1; + return (count[item.category] <= displayCount); + }; + return f; + }(); + response(result.filter(counter)); + }, + response: function(event, ui) { + if (!ui.content.length) { + ui.content.push(noResult); + } else { + $("#search").empty(); + } + }, + autoFocus: true, + position: { + collision: "flip" + }, + select: function(event, ui) { + if (ui.item.l !== noResult.l) { + var url = getURLPrefix(ui); + if (ui.item.category === catModules) { + if (useModuleDirectories) { + url += "module-summary.html"; + } else { + url = ui.item.l + "-summary.html"; + } + } else if (ui.item.category === catPackages) { + if (ui.item.url) { + url = ui.item.url; + } else { + url += ui.item.l.replace(/\./g, '/') + "/package-summary.html"; + } + } else if (ui.item.category === catTypes) { + if (ui.item.url) { + url = ui.item.url; + } else if (ui.item.p === "") { + url += ui.item.l + ".html"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; + } + } else if (ui.item.category === catMembers) { + if (ui.item.p === "") { + url += ui.item.c + ".html" + "#"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; + } + if (ui.item.url) { + url += ui.item.url; + } else { + url += ui.item.l; + } + } else if (ui.item.category === catSearchTags) { + url += ui.item.u; + } + if (top !== window) { + parent.classFrame.location = pathtoroot + url; + } else { + window.location.href = pathtoroot + url; + } + $("#search").focus(); + } + } + }); +}); diff --git a/docs/acf-jda/src-html/co/aikar/commands/CommandConfig.html b/docs/acf-jda/src-html/co/aikar/commands/CommandConfig.html index 15d37de9..b1b0da61 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/CommandConfig.html +++ b/docs/acf-jda/src-html/co/aikar/commands/CommandConfig.html @@ -1,26 +1,27 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      -004import org.jetbrains.annotations.NotNull;
      -005
      -006import java.util.List;
      -007
      -008public interface CommandConfig extends CommandConfigProvider {
      -009    @NotNull List<String> getCommandPrefixes();
      -010
      -011    @Override
      -012    default CommandConfig provide(MessageReceivedEvent event) {
      -013        return this;
      -014    }
      -015}
      +
      001package co.aikar.commands;
      +002
      +003import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      +004import org.jetbrains.annotations.NotNull;
      +005
      +006import java.util.List;
      +007
      +008public interface CommandConfig extends CommandConfigProvider {
      +009    @NotNull List<String> getCommandPrefixes();
      +010
      +011    @Override
      +012    default CommandConfig provide(MessageReceivedEvent event) {
      +013        return this;
      +014    }
      +015}
       
       
       
      @@ -83,5 +84,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/CommandConfigProvider.html b/docs/acf-jda/src-html/co/aikar/commands/CommandConfigProvider.html index 7efbde2d..b758da4e 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/CommandConfigProvider.html +++ b/docs/acf-jda/src-html/co/aikar/commands/CommandConfigProvider.html @@ -1,18 +1,19 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      -004
      -005public interface CommandConfigProvider {
      -006    CommandConfig provide(MessageReceivedEvent event);
      -007}
      +
      001package co.aikar.commands;
      +002
      +003import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      +004
      +005public interface CommandConfigProvider {
      +006    CommandConfig provide(MessageReceivedEvent event);
      +007}
       
       
       
      @@ -75,5 +76,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/CommandPermissionResolver.html b/docs/acf-jda/src-html/co/aikar/commands/CommandPermissionResolver.html index a640ac41..e1a0fb55 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/CommandPermissionResolver.html +++ b/docs/acf-jda/src-html/co/aikar/commands/CommandPermissionResolver.html @@ -1,17 +1,18 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003
      -004public interface CommandPermissionResolver {
      -005    boolean hasPermission(JDACommandManager manager, JDACommandEvent event, String permission);
      -006}
      +
      001package co.aikar.commands;
      +002
      +003
      +004public interface CommandPermissionResolver {
      +005    boolean hasPermission(JDACommandManager manager, JDACommandEvent event, String permission);
      +006}
       
       
       
      @@ -74,5 +75,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDACommandCompletions.html b/docs/acf-jda/src-html/co/aikar/commands/JDACommandCompletions.html index 49df1741..9168336a 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDACommandCompletions.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDACommandCompletions.html @@ -1,53 +1,54 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import org.jetbrains.annotations.NotNull;
      -004
      -005import java.util.Collections;
      -006import java.util.List;
      -007
      -008public class JDACommandCompletions extends CommandCompletions<CommandCompletionContext<?>> {
      -009    private boolean initialized;
      -010
      -011    public JDACommandCompletions(CommandManager manager) {
      -012        super(manager);
      -013        this.initialized = true;
      -014    }
      -015
      -016    @Override
      -017    public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<CommandCompletionContext<?>> handler) {
      -018        if (initialized) {
      -019            throw new UnsupportedOperationException("JDA Doesn't support Command Completions");
      -020        }
      -021        return null;
      -022    }
      -023
      -024    @Override
      -025    public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<CommandCompletionContext<?>> handler) {
      -026        if (initialized) {
      -027            throw new UnsupportedOperationException("JDA Doesn't support Command Completions");
      -028        }
      -029        return null;
      -030    }
      -031
      -032    @NotNull
      -033    @Override
      -034    List<String> of(RegisteredCommand command, CommandIssuer sender, String[] args, boolean isAsync) {
      -035        return Collections.emptyList();
      -036    }
      -037
      -038    @Override
      -039    List<String> getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) {
      -040        return Collections.emptyList();
      -041    }
      -042}
      +
      001package co.aikar.commands;
      +002
      +003import org.jetbrains.annotations.NotNull;
      +004
      +005import java.util.Collections;
      +006import java.util.List;
      +007
      +008public class JDACommandCompletions extends CommandCompletions<CommandCompletionContext<?>> {
      +009    private boolean initialized;
      +010
      +011    public JDACommandCompletions(CommandManager manager) {
      +012        super(manager);
      +013        this.initialized = true;
      +014    }
      +015
      +016    @Override
      +017    public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler<CommandCompletionContext<?>> handler) {
      +018        if (initialized) {
      +019            throw new UnsupportedOperationException("JDA Doesn't support Command Completions");
      +020        }
      +021        return null;
      +022    }
      +023
      +024    @Override
      +025    public CommandCompletionHandler registerAsyncCompletion(String id, AsyncCommandCompletionHandler<CommandCompletionContext<?>> handler) {
      +026        if (initialized) {
      +027            throw new UnsupportedOperationException("JDA Doesn't support Command Completions");
      +028        }
      +029        return null;
      +030    }
      +031
      +032    @NotNull
      +033    @Override
      +034    List<String> of(RegisteredCommand command, CommandIssuer sender, String[] args, boolean isAsync) {
      +035        return Collections.emptyList();
      +036    }
      +037
      +038    @Override
      +039    List<String> getCompletionValues(RegisteredCommand command, CommandIssuer sender, String completion, String[] args, boolean isAsync) {
      +040        return Collections.emptyList();
      +041    }
      +042}
       
       
       
      @@ -110,5 +111,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDACommandConfig.html b/docs/acf-jda/src-html/co/aikar/commands/JDACommandConfig.html index cb72a25d..6295cadc 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDACommandConfig.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDACommandConfig.html @@ -1,30 +1,31 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import org.jetbrains.annotations.NotNull;
      -004
      -005import java.util.List;
      -006import java.util.concurrent.CopyOnWriteArrayList;
      -007
      -008public class JDACommandConfig implements CommandConfig {
      -009    protected @NotNull List<String> commandPrefixes = new CopyOnWriteArrayList<>(new String[]{"!"});
      -010
      -011    public JDACommandConfig() {
      -012
      -013    }
      -014
      -015    @NotNull
      -016    public List<String> getCommandPrefixes() {
      -017        return commandPrefixes;
      -018    }
      -019}
      +
      001package co.aikar.commands;
      +002
      +003import org.jetbrains.annotations.NotNull;
      +004
      +005import java.util.List;
      +006import java.util.concurrent.CopyOnWriteArrayList;
      +007
      +008public class JDACommandConfig implements CommandConfig {
      +009    protected @NotNull List<String> commandPrefixes = new CopyOnWriteArrayList<>(new String[]{"!"});
      +010
      +011    public JDACommandConfig() {
      +012
      +013    }
      +014
      +015    @NotNull
      +016    public List<String> getCommandPrefixes() {
      +017        return commandPrefixes;
      +018    }
      +019}
       
       
       
      @@ -87,5 +88,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDACommandContexts.html b/docs/acf-jda/src-html/co/aikar/commands/JDACommandContexts.html index ce2a8ca0..fecd36e0 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDACommandContexts.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDACommandContexts.html @@ -1,127 +1,128 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import co.aikar.commands.annotation.Author;
      -004import co.aikar.commands.annotation.CrossGuild;
      -005import co.aikar.commands.annotation.Optional;
      -006import co.aikar.commands.annotation.SelfUser;
      -007import net.dv8tion.jda.core.JDA;
      -008import net.dv8tion.jda.core.entities.ChannelType;
      -009import net.dv8tion.jda.core.entities.Guild;
      -010import net.dv8tion.jda.core.entities.Message;
      -011import net.dv8tion.jda.core.entities.MessageChannel;
      -012import net.dv8tion.jda.core.entities.Role;
      -013import net.dv8tion.jda.core.entities.TextChannel;
      -014import net.dv8tion.jda.core.entities.User;
      -015import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      -016
      -017import java.util.List;
      -018
      -019// TODO: Message Keys !!!
      -020public class JDACommandContexts extends CommandContexts<JDACommandExecutionContext> {
      -021    private final JDACommandManager manager;
      -022    private final JDA jda;
      -023
      -024    public JDACommandContexts(JDACommandManager manager) {
      -025        super(manager);
      -026        this.manager = manager;
      -027        this.jda = this.manager.getJDA();
      -028        this.registerIssuerOnlyContext(JDACommandEvent.class, CommandExecutionContext::getIssuer);
      -029        this.registerIssuerOnlyContext(MessageReceivedEvent.class, c -> c.getIssuer().getIssuer());
      -030        this.registerIssuerOnlyContext(Message.class, c -> c.issuer.getIssuer().getMessage());
      -031        this.registerIssuerOnlyContext(ChannelType.class, c -> c.issuer.getIssuer().getChannelType());
      -032        this.registerIssuerOnlyContext(JDA.class, c -> jda);
      -033        this.registerIssuerOnlyContext(Guild.class, c -> {
      -034            MessageReceivedEvent event = c.getIssuer().getIssuer();
      -035            if (event.isFromType(ChannelType.PRIVATE) && !c.isOptional()) {
      -036                throw new InvalidCommandArgument("This command can only be executed in a Guild.", false);
      -037            } else {
      -038                return event.getGuild();
      -039            }
      -040        });
      -041        this.registerIssuerAwareContext(MessageChannel.class, c -> {
      -042            if (c.hasAnnotation(Author.class)) {
      -043                return c.issuer.getIssuer().getChannel();
      -044            }
      -045            boolean isCrossGuild = c.hasAnnotation(CrossGuild.class);
      -046            String argument = c.popFirstArg(); // we pop because we are only issuer aware if we are annotated
      -047            MessageChannel channel = null;
      -048            if (argument.startsWith("<#")) {
      -049                String id = argument.substring(2, argument.length() - 1);
      -050                channel = isCrossGuild ? jda.getTextChannelById(id) : c.issuer.getIssuer().getGuild().getTextChannelById(id);
      -051            } else {
      -052                List<TextChannel> channelList = isCrossGuild ? jda.getTextChannelsByName(argument, true) :
      -053                        c.issuer.getEvent().getGuild().getTextChannelsByName(argument, true);
      -054                if (channelList.size() > 1) {
      -055                    throw new InvalidCommandArgument("Too many channels were found with the given name. Try with the `#channelname` syntax.", false);
      -056                } else if (channelList.size() == 1) {
      -057                    channel = channelList.get(0);
      -058                }
      -059            }
      -060            if (channel == null) {
      -061                throw new InvalidCommandArgument("Couldn't find a channel with that name or ID.");
      -062            }
      -063            return channel;
      -064        });
      -065        this.registerIssuerAwareContext(User.class, c -> {
      -066            if (c.hasAnnotation(SelfUser.class)) {
      -067                return jda.getSelfUser();
      -068            }
      -069            String arg = c.getFirstArg();
      -070            if (c.isOptional() && (arg == null || arg.isEmpty())) {
      -071                return null;
      -072            }
      -073            arg = c.popFirstArg(); // we pop because we are only issuer aware if we are annotated
      -074            User user = null;
      -075            if (arg.startsWith("<@!")) { // for some reason a ! is added when @'ing and clicking their name.
      -076                user = jda.getUserById(arg.substring(3, arg.length() - 1));
      -077            } else if (arg.startsWith("<@")) { // users can /also/ be mentioned like this...
      -078                user = jda.getUserById(arg.substring(2, arg.length() - 1));
      -079            } else {
      -080                List<User> users = jda.getUsersByName(arg, true);
      -081                if (users.size() > 1) {
      -082                    throw new InvalidCommandArgument("Too many users were found with the given name. Try with the `@username#0000` syntax.", false);
      -083                }
      -084                if (!users.isEmpty()) {
      -085                    user = users.get(0);
      -086                }
      -087            }
      -088            if (user == null) {
      -089                throw new InvalidCommandArgument("Could not find a user with that name or ID.");
      -090            }
      -091            return user;
      -092        });
      -093        this.registerContext(Role.class, c -> {
      -094            boolean isCrossGuild = c.hasAnnotation(CrossGuild.class);
      -095            String arg = c.popFirstArg();
      -096            Role role = null;
      -097            if (arg.startsWith("<@&")) {
      -098                String id = arg.substring(3, arg.length() - 1);
      -099                role = isCrossGuild ? jda.getRoleById(id) : c.issuer.getIssuer().getGuild().getRoleById(id);
      -100            } else {
      -101                List<Role> roles = isCrossGuild ? jda.getRolesByName(arg, true)
      -102                        : c.issuer.getIssuer().getGuild().getRolesByName(arg, true);
      -103                if (roles.size() > 1) {
      -104                    throw new InvalidCommandArgument("Too many roles were found with the given name. Try with the `@role` syntax.", false);
      -105                }
      -106                if (!roles.isEmpty()) {
      -107                    role = roles.get(0);
      -108                }
      -109            }
      -110            if (role == null) {
      -111                throw new InvalidCommandArgument("Could not find a role with that name or ID.");
      -112            }
      -113            return role;
      -114        });
      -115    }
      -116}
      +
      001package co.aikar.commands;
      +002
      +003import co.aikar.commands.annotation.Author;
      +004import co.aikar.commands.annotation.CrossGuild;
      +005import co.aikar.commands.annotation.Optional;
      +006import co.aikar.commands.annotation.SelfUser;
      +007import net.dv8tion.jda.core.JDA;
      +008import net.dv8tion.jda.core.entities.ChannelType;
      +009import net.dv8tion.jda.core.entities.Guild;
      +010import net.dv8tion.jda.core.entities.Message;
      +011import net.dv8tion.jda.core.entities.MessageChannel;
      +012import net.dv8tion.jda.core.entities.Role;
      +013import net.dv8tion.jda.core.entities.TextChannel;
      +014import net.dv8tion.jda.core.entities.User;
      +015import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      +016
      +017import java.util.List;
      +018
      +019// TODO: Message Keys !!!
      +020public class JDACommandContexts extends CommandContexts<JDACommandExecutionContext> {
      +021    private final JDACommandManager manager;
      +022    private final JDA jda;
      +023
      +024    public JDACommandContexts(JDACommandManager manager) {
      +025        super(manager);
      +026        this.manager = manager;
      +027        this.jda = this.manager.getJDA();
      +028        this.registerIssuerOnlyContext(JDACommandEvent.class, CommandExecutionContext::getIssuer);
      +029        this.registerIssuerOnlyContext(MessageReceivedEvent.class, c -> c.getIssuer().getIssuer());
      +030        this.registerIssuerOnlyContext(Message.class, c -> c.issuer.getIssuer().getMessage());
      +031        this.registerIssuerOnlyContext(ChannelType.class, c -> c.issuer.getIssuer().getChannelType());
      +032        this.registerIssuerOnlyContext(JDA.class, c -> jda);
      +033        this.registerIssuerOnlyContext(Guild.class, c -> {
      +034            MessageReceivedEvent event = c.getIssuer().getIssuer();
      +035            if (event.isFromType(ChannelType.PRIVATE) && !c.isOptional()) {
      +036                throw new InvalidCommandArgument("This command can only be executed in a Guild.", false);
      +037            } else {
      +038                return event.getGuild();
      +039            }
      +040        });
      +041        this.registerIssuerAwareContext(MessageChannel.class, c -> {
      +042            if (c.hasAnnotation(Author.class)) {
      +043                return c.issuer.getIssuer().getChannel();
      +044            }
      +045            boolean isCrossGuild = c.hasAnnotation(CrossGuild.class);
      +046            String argument = c.popFirstArg(); // we pop because we are only issuer aware if we are annotated
      +047            MessageChannel channel = null;
      +048            if (argument.startsWith("<#")) {
      +049                String id = argument.substring(2, argument.length() - 1);
      +050                channel = isCrossGuild ? jda.getTextChannelById(id) : c.issuer.getIssuer().getGuild().getTextChannelById(id);
      +051            } else {
      +052                List<TextChannel> channelList = isCrossGuild ? jda.getTextChannelsByName(argument, true) :
      +053                        c.issuer.getEvent().getGuild().getTextChannelsByName(argument, true);
      +054                if (channelList.size() > 1) {
      +055                    throw new InvalidCommandArgument("Too many channels were found with the given name. Try with the `#channelname` syntax.", false);
      +056                } else if (channelList.size() == 1) {
      +057                    channel = channelList.get(0);
      +058                }
      +059            }
      +060            if (channel == null) {
      +061                throw new InvalidCommandArgument("Couldn't find a channel with that name or ID.");
      +062            }
      +063            return channel;
      +064        });
      +065        this.registerIssuerAwareContext(User.class, c -> {
      +066            if (c.hasAnnotation(SelfUser.class)) {
      +067                return jda.getSelfUser();
      +068            }
      +069            String arg = c.getFirstArg();
      +070            if (c.isOptional() && (arg == null || arg.isEmpty())) {
      +071                return null;
      +072            }
      +073            arg = c.popFirstArg(); // we pop because we are only issuer aware if we are annotated
      +074            User user = null;
      +075            if (arg.startsWith("<@!")) { // for some reason a ! is added when @'ing and clicking their name.
      +076                user = jda.getUserById(arg.substring(3, arg.length() - 1));
      +077            } else if (arg.startsWith("<@")) { // users can /also/ be mentioned like this...
      +078                user = jda.getUserById(arg.substring(2, arg.length() - 1));
      +079            } else {
      +080                List<User> users = jda.getUsersByName(arg, true);
      +081                if (users.size() > 1) {
      +082                    throw new InvalidCommandArgument("Too many users were found with the given name. Try with the `@username#0000` syntax.", false);
      +083                }
      +084                if (!users.isEmpty()) {
      +085                    user = users.get(0);
      +086                }
      +087            }
      +088            if (user == null) {
      +089                throw new InvalidCommandArgument("Could not find a user with that name or ID.");
      +090            }
      +091            return user;
      +092        });
      +093        this.registerContext(Role.class, c -> {
      +094            boolean isCrossGuild = c.hasAnnotation(CrossGuild.class);
      +095            String arg = c.popFirstArg();
      +096            Role role = null;
      +097            if (arg.startsWith("<@&")) {
      +098                String id = arg.substring(3, arg.length() - 1);
      +099                role = isCrossGuild ? jda.getRoleById(id) : c.issuer.getIssuer().getGuild().getRoleById(id);
      +100            } else {
      +101                List<Role> roles = isCrossGuild ? jda.getRolesByName(arg, true)
      +102                        : c.issuer.getIssuer().getGuild().getRolesByName(arg, true);
      +103                if (roles.size() > 1) {
      +104                    throw new InvalidCommandArgument("Too many roles were found with the given name. Try with the `@role` syntax.", false);
      +105                }
      +106                if (!roles.isEmpty()) {
      +107                    role = roles.get(0);
      +108                }
      +109            }
      +110            if (role == null) {
      +111                throw new InvalidCommandArgument("Could not find a role with that name or ID.");
      +112            }
      +113            return role;
      +114        });
      +115    }
      +116}
       
       
       
      @@ -184,5 +185,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDACommandEvent.html b/docs/acf-jda/src-html/co/aikar/commands/JDACommandEvent.html index 7322e901..b28f3d5c 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDACommandEvent.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDACommandEvent.html @@ -1,77 +1,78 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import net.dv8tion.jda.core.entities.Message;
      -004import net.dv8tion.jda.core.entities.MessageEmbed;
      -005import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      -006import org.jetbrains.annotations.NotNull;
      -007
      -008import java.util.UUID;
      -009
      -010public class JDACommandEvent implements CommandIssuer {
      -011
      -012    private MessageReceivedEvent event;
      -013    private JDACommandManager manager;
      -014
      -015    public JDACommandEvent(JDACommandManager manager, MessageReceivedEvent event) {
      -016
      -017        this.manager = manager;
      -018        this.event = event;
      -019    }
      -020
      -021    public MessageReceivedEvent getEvent() {
      -022        return event;
      -023    }
      -024
      -025    @Override
      -026    public MessageReceivedEvent getIssuer() {
      -027        return event;
      -028    }
      -029
      -030    @Override
      -031    public CommandManager getManager() {
      -032        return this.manager;
      -033    }
      -034
      -035    @Override
      -036    public boolean isPlayer() {
      -037        return false;
      -038    }
      -039
      -040    @Override
      -041    public @NotNull UUID getUniqueId() {
      -042        // Discord id only have 64 bit width (long) while UUIDs have twice the size.
      -043        // In order to keep it unique we use 0L for the first 64 bit.
      -044        long authorId = event.getAuthor().getIdLong();
      -045        return new UUID(0, authorId);
      -046    }
      -047
      -048    @Override
      -049    public boolean hasPermission(String permission) {
      -050        CommandPermissionResolver permissionResolver = this.manager.getPermissionResolver();
      -051        return permissionResolver == null || permissionResolver.hasPermission(manager, this, permission);
      -052    }
      -053
      -054    @Override
      -055    public void sendMessageInternal(String message) {
      -056        this.event.getChannel().sendMessage(message).queue();
      -057    }
      -058
      -059    public void sendMessage(Message message) {
      -060        this.event.getChannel().sendMessage(message).queue();
      -061    }
      -062
      -063    public void sendMessage(MessageEmbed message) {
      -064        this.event.getChannel().sendMessage(message).queue();
      -065    }
      -066}
      +
      001package co.aikar.commands;
      +002
      +003import net.dv8tion.jda.core.entities.Message;
      +004import net.dv8tion.jda.core.entities.MessageEmbed;
      +005import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      +006import org.jetbrains.annotations.NotNull;
      +007
      +008import java.util.UUID;
      +009
      +010public class JDACommandEvent implements CommandIssuer {
      +011
      +012    private MessageReceivedEvent event;
      +013    private JDACommandManager manager;
      +014
      +015    public JDACommandEvent(JDACommandManager manager, MessageReceivedEvent event) {
      +016
      +017        this.manager = manager;
      +018        this.event = event;
      +019    }
      +020
      +021    public MessageReceivedEvent getEvent() {
      +022        return event;
      +023    }
      +024
      +025    @Override
      +026    public MessageReceivedEvent getIssuer() {
      +027        return event;
      +028    }
      +029
      +030    @Override
      +031    public CommandManager getManager() {
      +032        return this.manager;
      +033    }
      +034
      +035    @Override
      +036    public boolean isPlayer() {
      +037        return false;
      +038    }
      +039
      +040    @Override
      +041    public @NotNull UUID getUniqueId() {
      +042        // Discord id only have 64 bit width (long) while UUIDs have twice the size.
      +043        // In order to keep it unique we use 0L for the first 64 bit.
      +044        long authorId = event.getAuthor().getIdLong();
      +045        return new UUID(0, authorId);
      +046    }
      +047
      +048    @Override
      +049    public boolean hasPermission(String permission) {
      +050        CommandPermissionResolver permissionResolver = this.manager.getPermissionResolver();
      +051        return permissionResolver == null || permissionResolver.hasPermission(manager, this, permission);
      +052    }
      +053
      +054    @Override
      +055    public void sendMessageInternal(String message) {
      +056        this.event.getChannel().sendMessage(message).queue();
      +057    }
      +058
      +059    public void sendMessage(Message message) {
      +060        this.event.getChannel().sendMessage(message).queue();
      +061    }
      +062
      +063    public void sendMessage(MessageEmbed message) {
      +064        this.event.getChannel().sendMessage(message).queue();
      +065    }
      +066}
       
       
       
      @@ -134,5 +135,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDACommandExecutionContext.html b/docs/acf-jda/src-html/co/aikar/commands/JDACommandExecutionContext.html index 148e7100..fe4f63a9 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDACommandExecutionContext.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDACommandExecutionContext.html @@ -1,21 +1,22 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import java.util.List;
      -004import java.util.Map;
      -005
      -006public class JDACommandExecutionContext extends CommandExecutionContext<JDACommandExecutionContext, JDACommandEvent> {
      -007    JDACommandExecutionContext(RegisteredCommand cmd, CommandParameter param, JDACommandEvent sender, List<String> args, int index, Map<String, Object> passedArgs) {
      -008        super(cmd, param, sender, args, index, passedArgs);
      -009    }
      -010}
      +
      001package co.aikar.commands;
      +002
      +003import java.util.List;
      +004import java.util.Map;
      +005
      +006public class JDACommandExecutionContext extends CommandExecutionContext<JDACommandExecutionContext, JDACommandEvent> {
      +007    JDACommandExecutionContext(RegisteredCommand cmd, CommandParameter param, JDACommandEvent sender, List<String> args, int index, Map<String, Object> passedArgs) {
      +008        super(cmd, param, sender, args, index, passedArgs);
      +009    }
      +010}
       
       
       
      @@ -78,5 +79,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDACommandManager.html b/docs/acf-jda/src-html/co/aikar/commands/JDACommandManager.html index 3f3f0ac3..df6decfa 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDACommandManager.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDACommandManager.html @@ -1,300 +1,302 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
      -004import net.dv8tion.jda.core.AccountType;
      -005import net.dv8tion.jda.core.JDA;
      -006import net.dv8tion.jda.core.entities.ChannelType;
      -007import net.dv8tion.jda.core.entities.Message;
      -008import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      -009import org.jetbrains.annotations.NotNull;
      -010
      -011import java.util.Arrays;
      -012import java.util.HashMap;
      -013import java.util.Collection;
      -014import java.util.Collections;
      -015import java.util.List;
      -016import java.util.Map;
      -017import java.util.logging.Level;
      -018import java.util.logging.Logger;
      -019
      -020public class JDACommandManager extends CommandManager<
      -021        MessageReceivedEvent,
      -022        JDACommandEvent,
      -023        String,
      -024        MessageFormatter<String>,
      -025        JDACommandExecutionContext,
      -026        JDAConditionContext
      -027        > {
      -028
      -029    private final JDA jda;
      -030    protected JDACommandCompletions completions;
      -031    protected JDACommandContexts contexts;
      -032    protected JDALocales locales;
      -033    protected Map<String, JDARootCommand> commands = new HashMap<>();
      -034    private Logger logger;
      -035    private CommandConfig defaultConfig;
      -036    private CommandConfigProvider configProvider;
      -037    private CommandPermissionResolver permissionResolver;
      -038    private long botOwner = 0L;
      -039
      -040    public JDACommandManager(JDA jda) {
      -041        this(jda, null);
      -042    }
      -043
      -044    public JDACommandManager(JDA jda, JDAOptions options) {
      -045        if (options == null) {
      -046            options = new JDAOptions();
      -047        }
      -048        this.jda = jda;
      -049        this.permissionResolver = options.permissionResolver;
      -050        jda.addEventListener(new JDAListener(this));
      -051        this.defaultConfig = options.defaultConfig == null ? new JDACommandConfig() : options.defaultConfig;
      -052        this.configProvider = options.configProvider;
      -053        this.defaultFormatter = new JDAMessageFormatter();
      -054        this.completions = new JDACommandCompletions(this);
      -055        this.logger = Logger.getLogger(this.getClass().getSimpleName());
      -056
      -057        getCommandConditions().addCondition("owneronly", context -> {
      -058            if (context.getIssuer().getEvent().getAuthor().getIdLong() != getBotOwnerId()) {
      -059                throw new ConditionFailedException("Only the bot owner can use this command."); // TODO: MessageKey
      -060            }
      -061        });
      -062
      -063        getCommandConditions().addCondition("guildonly", context -> {
      -064            if (context.getIssuer().getEvent().getChannelType() != ChannelType.TEXT) {
      -065                throw new ConditionFailedException("This command must be used in guild chat."); // TODO: MessageKey
      -066            }
      -067        });
      -068
      -069        getCommandConditions().addCondition("privateonly", context -> {
      -070            if (context.getIssuer().getEvent().getChannelType() != ChannelType.PRIVATE) {
      -071                throw new ConditionFailedException("This command must be used in private chat."); // TODO: MessageKey
      -072            }
      -073        });
      -074
      -075        getCommandConditions().addCondition("grouponly", context -> {
      -076            if (context.getIssuer().getEvent().getChannelType() != ChannelType.GROUP) {
      -077                throw new ConditionFailedException("This command must be used in group chat."); // TODO: MessageKey
      -078            }
      -079        });
      -080    }
      -081
      -082    public static JDAOptions options() {
      -083        return new JDAOptions();
      -084    }
      -085
      -086    void initializeBotOwner() {
      -087        if (botOwner == 0L) {
      -088            if (jda.getAccountType() == AccountType.BOT) {
      -089                botOwner = jda.asBot().getApplicationInfo().complete().getOwner().getIdLong();
      -090            } else {
      -091                botOwner = jda.getSelfUser().getIdLong();
      -092            }
      -093        }
      -094    }
      -095
      -096    public long getBotOwnerId() {
      -097        // Just in case initialization on ReadyEvent fails.
      -098        initializeBotOwner();
      -099        return botOwner;
      -100    }
      -101
      -102    public JDA getJDA() {
      -103        return jda;
      -104    }
      -105
      -106    public Logger getLogger() {
      -107        return logger;
      -108    }
      -109
      -110    public void setLogger(Logger logger) {
      -111        this.logger = logger;
      -112    }
      -113
      -114    public CommandConfig getDefaultConfig() {
      -115        return defaultConfig;
      -116    }
      -117
      -118    public void setDefaultConfig(@NotNull CommandConfig defaultConfig) {
      -119        this.defaultConfig = defaultConfig;
      -120    }
      -121
      -122    public CommandConfigProvider getConfigProvider() {
      -123        return configProvider;
      -124    }
      -125
      -126    public void setConfigProvider(CommandConfigProvider configProvider) {
      -127        this.configProvider = configProvider;
      -128    }
      -129
      -130    public CommandPermissionResolver getPermissionResolver() {
      -131        return permissionResolver;
      -132    }
      -133
      -134    public void setPermissionResolver(CommandPermissionResolver permissionResolver) {
      -135        this.permissionResolver = permissionResolver;
      -136    }
      -137
      -138    @Override
      -139    public CommandContexts<?> getCommandContexts() {
      -140        if (this.contexts == null) {
      -141            this.contexts = new JDACommandContexts(this);
      -142        }
      -143        return this.contexts;
      -144    }
      -145
      -146    @Override
      -147    public CommandCompletions<?> getCommandCompletions() {
      -148        return this.completions;
      -149    }
      -150
      -151    @Override
      -152    public void registerCommand(BaseCommand command) {
      -153        command.onRegister(this);
      -154        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
      -155            String commandName = entry.getKey().toLowerCase();
      -156            JDARootCommand cmd = (JDARootCommand) entry.getValue();
      -157            if (!cmd.isRegistered) {
      -158                cmd.isRegistered = true;
      -159                commands.put(commandName, cmd);
      -160            }
      -161        }
      -162    }
      -163
      -164    public void unregisterCommand(BaseCommand command) {
      -165        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
      -166            String jdaCommandName = entry.getKey().toLowerCase();
      -167            JDARootCommand jdaCommand = (JDARootCommand) entry.getValue();
      -168            jdaCommand.getSubCommands().values().removeAll(command.subCommands.values());
      -169            if (jdaCommand.isRegistered && jdaCommand.getSubCommands().isEmpty()) {
      -170                jdaCommand.isRegistered = false;
      -171                commands.remove(jdaCommandName);
      -172            }
      -173        }
      -174    }
      -175
      -176    @Override
      -177    public boolean hasRegisteredCommands() {
      -178        return !this.commands.isEmpty();
      -179    }
      -180
      -181    @Override
      -182    public boolean isCommandIssuer(Class<?> type) {
      -183        return JDACommandEvent.class.isAssignableFrom(type);
      -184    }
      -185
      -186    @Override
      -187    public JDACommandEvent getCommandIssuer(Object issuer) {
      -188        if (!(issuer instanceof MessageReceivedEvent)) {
      -189            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Message Received Event.");
      -190        }
      -191        return new JDACommandEvent(this, (MessageReceivedEvent) issuer);
      -192    }
      -193
      -194    @Override
      -195    public RootCommand createRootCommand(String cmd) {
      -196        return new JDARootCommand(this, cmd);
      -197    }
      -198
      -199    @Override
      -200    public Collection<RootCommand> getRegisteredRootCommands() {
      -201        return Collections.unmodifiableCollection(commands.values());
      -202    }
      -203
      -204    @Override
      -205    public Locales getLocales() {
      -206        if (this.locales == null) {
      -207            this.locales = new JDALocales(this);
      -208            this.locales.loadLanguages();
      -209        }
      -210        return this.locales;
      -211    }
      -212
      -213    @Override
      -214    public CommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
      -215        return new JDACommandExecutionContext(command, parameter, (JDACommandEvent) sender, args, i, passedArgs);
      -216    }
      -217
      -218    @Override
      -219    public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
      -220        // Not really going to be used;
      -221        //noinspection unchecked
      -222        return new CommandCompletionContext(command, sender, input, config, args);
      -223    }
      -224
      -225    @Override
      -226    public void log(LogLevel level, String message, Throwable throwable) {
      -227        Level logLevel = level == LogLevel.INFO ? Level.INFO : Level.SEVERE;
      -228        logger.log(logLevel, LogLevel.LOG_PREFIX + message);
      -229        if (throwable != null) {
      -230            for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
      -231                logger.log(logLevel, LogLevel.LOG_PREFIX + line);
      -232            }
      -233        }
      -234    }
      -235
      -236    void dispatchEvent(MessageReceivedEvent event) {
      -237        Message message = event.getMessage();
      -238        String msg = message.getContentRaw();
      -239
      -240        CommandConfig config = getCommandConfig(event);
      -241
      -242        String prefixFound = null;
      -243        for (String prefix : config.getCommandPrefixes()) {
      -244            if (msg.startsWith(prefix)) {
      -245                prefixFound = prefix;
      -246                break;
      -247            }
      -248        }
      -249        if (prefixFound == null) {
      -250            return;
      -251        }
      -252
      -253        String[] args = ACFPatterns.SPACE.split(msg.substring(prefixFound.length()), -1);
      -254        if (args.length == 0) {
      -255            return;
      -256        }
      -257        String cmd = args[0].toLowerCase();
      -258        JDARootCommand rootCommand = this.commands.get(cmd);
      -259        if (rootCommand == null) {
      -260            return;
      -261        }
      -262        if (args.length > 1) {
      -263            args = Arrays.copyOfRange(args, 1, args.length);
      -264        } else {
      -265            args = new String[0];
      -266        }
      -267        rootCommand.execute(this.getCommandIssuer(event), cmd, args);
      -268    }
      -269
      -270    private CommandConfig getCommandConfig(MessageReceivedEvent event) {
      -271        CommandConfig config = this.defaultConfig;
      -272        if (this.configProvider != null) {
      -273            CommandConfig provided = this.configProvider.provide(event);
      -274            if (provided != null) {
      -275                config = provided;
      -276            }
      -277        }
      -278        return config;
      -279    }
      -280
      -281
      -282    @Override
      -283    public String getCommandPrefix(CommandIssuer issuer) {
      -284        MessageReceivedEvent event = ((JDACommandEvent) issuer).getEvent();
      -285        CommandConfig commandConfig = getCommandConfig(event);
      -286        List<String> prefixes = commandConfig.getCommandPrefixes();
      -287        return prefixes.isEmpty() ? "" : prefixes.get(0);
      -288    }
      -289}
      +
      001package co.aikar.commands;
      +002
      +003import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
      +004import net.dv8tion.jda.core.AccountType;
      +005import net.dv8tion.jda.core.JDA;
      +006import net.dv8tion.jda.core.entities.ChannelType;
      +007import net.dv8tion.jda.core.entities.Message;
      +008import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      +009import org.jetbrains.annotations.NotNull;
      +010
      +011import java.util.Arrays;
      +012import java.util.HashMap;
      +013import java.util.Collection;
      +014import java.util.Collections;
      +015import java.util.List;
      +016import java.util.Locale;
      +017import java.util.Map;
      +018import java.util.logging.Level;
      +019import java.util.logging.Logger;
      +020
      +021public class JDACommandManager extends CommandManager<
      +022        MessageReceivedEvent,
      +023        JDACommandEvent,
      +024        String,
      +025        MessageFormatter<String>,
      +026        JDACommandExecutionContext,
      +027        JDAConditionContext
      +028        > {
      +029
      +030    private final JDA jda;
      +031    protected JDACommandCompletions completions;
      +032    protected JDACommandContexts contexts;
      +033    protected JDALocales locales;
      +034    protected Map<String, JDARootCommand> commands = new HashMap<>();
      +035    private Logger logger;
      +036    private CommandConfig defaultConfig;
      +037    private CommandConfigProvider configProvider;
      +038    private CommandPermissionResolver permissionResolver;
      +039    private long botOwner = 0L;
      +040
      +041    public JDACommandManager(JDA jda) {
      +042        this(jda, null);
      +043    }
      +044
      +045    public JDACommandManager(JDA jda, JDAOptions options) {
      +046        if (options == null) {
      +047            options = new JDAOptions();
      +048        }
      +049        this.jda = jda;
      +050        this.permissionResolver = options.permissionResolver;
      +051        jda.addEventListener(new JDAListener(this));
      +052        this.defaultConfig = options.defaultConfig == null ? new JDACommandConfig() : options.defaultConfig;
      +053        this.configProvider = options.configProvider;
      +054        this.defaultFormatter = new JDAMessageFormatter();
      +055        this.completions = new JDACommandCompletions(this);
      +056        this.logger = Logger.getLogger(this.getClass().getSimpleName());
      +057
      +058        getCommandConditions().addCondition("owneronly", context -> {
      +059            if (context.getIssuer().getEvent().getAuthor().getIdLong() != getBotOwnerId()) {
      +060                throw new ConditionFailedException("Only the bot owner can use this command."); // TODO: MessageKey
      +061            }
      +062        });
      +063
      +064        getCommandConditions().addCondition("guildonly", context -> {
      +065            if (context.getIssuer().getEvent().getChannelType() != ChannelType.TEXT) {
      +066                throw new ConditionFailedException("This command must be used in guild chat."); // TODO: MessageKey
      +067            }
      +068        });
      +069
      +070        getCommandConditions().addCondition("privateonly", context -> {
      +071            if (context.getIssuer().getEvent().getChannelType() != ChannelType.PRIVATE) {
      +072                throw new ConditionFailedException("This command must be used in private chat."); // TODO: MessageKey
      +073            }
      +074        });
      +075
      +076        getCommandConditions().addCondition("grouponly", context -> {
      +077            if (context.getIssuer().getEvent().getChannelType() != ChannelType.GROUP) {
      +078                throw new ConditionFailedException("This command must be used in group chat."); // TODO: MessageKey
      +079            }
      +080        });
      +081    }
      +082
      +083    public static JDAOptions options() {
      +084        return new JDAOptions();
      +085    }
      +086
      +087    void initializeBotOwner() {
      +088        if (botOwner == 0L) {
      +089            if (jda.getAccountType() == AccountType.BOT) {
      +090                botOwner = jda.asBot().getApplicationInfo().complete().getOwner().getIdLong();
      +091            } else {
      +092                botOwner = jda.getSelfUser().getIdLong();
      +093            }
      +094        }
      +095    }
      +096
      +097    public long getBotOwnerId() {
      +098        // Just in case initialization on ReadyEvent fails.
      +099        initializeBotOwner();
      +100        return botOwner;
      +101    }
      +102
      +103    public JDA getJDA() {
      +104        return jda;
      +105    }
      +106
      +107    public Logger getLogger() {
      +108        return logger;
      +109    }
      +110
      +111    public void setLogger(Logger logger) {
      +112        this.logger = logger;
      +113    }
      +114
      +115    public CommandConfig getDefaultConfig() {
      +116        return defaultConfig;
      +117    }
      +118
      +119    public void setDefaultConfig(@NotNull CommandConfig defaultConfig) {
      +120        this.defaultConfig = defaultConfig;
      +121    }
      +122
      +123    public CommandConfigProvider getConfigProvider() {
      +124        return configProvider;
      +125    }
      +126
      +127    public void setConfigProvider(CommandConfigProvider configProvider) {
      +128        this.configProvider = configProvider;
      +129    }
      +130
      +131    public CommandPermissionResolver getPermissionResolver() {
      +132        return permissionResolver;
      +133    }
      +134
      +135    public void setPermissionResolver(CommandPermissionResolver permissionResolver) {
      +136        this.permissionResolver = permissionResolver;
      +137    }
      +138
      +139    @Override
      +140    public CommandContexts<?> getCommandContexts() {
      +141        if (this.contexts == null) {
      +142            this.contexts = new JDACommandContexts(this);
      +143        }
      +144        return this.contexts;
      +145    }
      +146
      +147    @Override
      +148    public CommandCompletions<?> getCommandCompletions() {
      +149        return this.completions;
      +150    }
      +151
      +152    @Override
      +153    public void registerCommand(BaseCommand command) {
      +154        command.onRegister(this);
      +155        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
      +156            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
      +157            JDARootCommand cmd = (JDARootCommand) entry.getValue();
      +158            if (!cmd.isRegistered) {
      +159                cmd.isRegistered = true;
      +160                commands.put(commandName, cmd);
      +161            }
      +162        }
      +163    }
      +164
      +165    public void unregisterCommand(BaseCommand command) {
      +166        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
      +167            String jdaCommandName = entry.getKey().toLowerCase(Locale.ENGLISH);
      +168            JDARootCommand jdaCommand = (JDARootCommand) entry.getValue();
      +169            jdaCommand.getSubCommands().values().removeAll(command.subCommands.values());
      +170            if (jdaCommand.isRegistered && jdaCommand.getSubCommands().isEmpty()) {
      +171                jdaCommand.isRegistered = false;
      +172                commands.remove(jdaCommandName);
      +173            }
      +174        }
      +175    }
      +176
      +177    @Override
      +178    public boolean hasRegisteredCommands() {
      +179        return !this.commands.isEmpty();
      +180    }
      +181
      +182    @Override
      +183    public boolean isCommandIssuer(Class<?> type) {
      +184        return JDACommandEvent.class.isAssignableFrom(type);
      +185    }
      +186
      +187    @Override
      +188    public JDACommandEvent getCommandIssuer(Object issuer) {
      +189        if (!(issuer instanceof MessageReceivedEvent)) {
      +190            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Message Received Event.");
      +191        }
      +192        return new JDACommandEvent(this, (MessageReceivedEvent) issuer);
      +193    }
      +194
      +195    @Override
      +196    public RootCommand createRootCommand(String cmd) {
      +197        return new JDARootCommand(this, cmd);
      +198    }
      +199
      +200    @Override
      +201    public Collection<RootCommand> getRegisteredRootCommands() {
      +202        return Collections.unmodifiableCollection(commands.values());
      +203    }
      +204
      +205    @Override
      +206    public Locales getLocales() {
      +207        if (this.locales == null) {
      +208            this.locales = new JDALocales(this);
      +209            this.locales.loadLanguages();
      +210        }
      +211        return this.locales;
      +212    }
      +213
      +214    @Override
      +215    public CommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
      +216        return new JDACommandExecutionContext(command, parameter, (JDACommandEvent) sender, args, i, passedArgs);
      +217    }
      +218
      +219    @Override
      +220    public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
      +221        // Not really going to be used;
      +222        //noinspection unchecked
      +223        return new CommandCompletionContext(command, sender, input, config, args);
      +224    }
      +225
      +226    @Override
      +227    public void log(LogLevel level, String message, Throwable throwable) {
      +228        Level logLevel = level == LogLevel.INFO ? Level.INFO : Level.SEVERE;
      +229        logger.log(logLevel, LogLevel.LOG_PREFIX + message);
      +230        if (throwable != null) {
      +231            for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
      +232                logger.log(logLevel, LogLevel.LOG_PREFIX + line);
      +233            }
      +234        }
      +235    }
      +236
      +237    void dispatchEvent(MessageReceivedEvent event) {
      +238        Message message = event.getMessage();
      +239        String msg = message.getContentRaw();
      +240
      +241        CommandConfig config = getCommandConfig(event);
      +242
      +243        String prefixFound = null;
      +244        for (String prefix : config.getCommandPrefixes()) {
      +245            if (msg.startsWith(prefix)) {
      +246                prefixFound = prefix;
      +247                break;
      +248            }
      +249        }
      +250        if (prefixFound == null) {
      +251            return;
      +252        }
      +253
      +254        String[] args = ACFPatterns.SPACE.split(msg.substring(prefixFound.length()), -1);
      +255        if (args.length == 0) {
      +256            return;
      +257        }
      +258        String cmd = args[0].toLowerCase(Locale.ENGLISH);
      +259        JDARootCommand rootCommand = this.commands.get(cmd);
      +260        if (rootCommand == null) {
      +261            return;
      +262        }
      +263        if (args.length > 1) {
      +264            args = Arrays.copyOfRange(args, 1, args.length);
      +265        } else {
      +266            args = new String[0];
      +267        }
      +268        rootCommand.execute(this.getCommandIssuer(event), cmd, args);
      +269    }
      +270
      +271    private CommandConfig getCommandConfig(MessageReceivedEvent event) {
      +272        CommandConfig config = this.defaultConfig;
      +273        if (this.configProvider != null) {
      +274            CommandConfig provided = this.configProvider.provide(event);
      +275            if (provided != null) {
      +276                config = provided;
      +277            }
      +278        }
      +279        return config;
      +280    }
      +281
      +282
      +283    @Override
      +284    public String getCommandPrefix(CommandIssuer issuer) {
      +285        MessageReceivedEvent event = ((JDACommandEvent) issuer).getEvent();
      +286        CommandConfig commandConfig = getCommandConfig(event);
      +287        List<String> prefixes = commandConfig.getCommandPrefixes();
      +288        return prefixes.isEmpty() ? "" : prefixes.get(0);
      +289    }
      +290}
       
       
       
      @@ -357,5 +359,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDACommandPermissionResolver.html b/docs/acf-jda/src-html/co/aikar/commands/JDACommandPermissionResolver.html index be04dfb4..a110d10a 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDACommandPermissionResolver.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDACommandPermissionResolver.html @@ -1,50 +1,52 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import net.dv8tion.jda.core.Permission;
      -004
      -005import java.util.HashMap;
      -006import java.util.Map;
      -007
      -008public class JDACommandPermissionResolver implements CommandPermissionResolver {
      -009    private Map<String, Integer> discordPermissionOffsets;
      -010
      -011    public JDACommandPermissionResolver() {
      -012        discordPermissionOffsets = new HashMap<>();
      -013        for (Permission permission : Permission.values()) {
      -014            discordPermissionOffsets.put(permission.name().toLowerCase().replaceAll("_", "-"), permission.getOffset());
      -015        }
      -016    }
      -017
      -018    @Override
      -019    public boolean hasPermission(JDACommandManager manager, JDACommandEvent event, String permission) {
      -020        // Explicitly return true if the issuer is the bot's owner. They are always allowed.
      -021        if (manager.getBotOwnerId() == event.getIssuer().getAuthor().getIdLong()) {
      -022            return true;
      -023        }
      -024
      -025        // Return false on webhook messages, as they cannot have permissions defined.
      -026        if (event.getIssuer().isWebhookMessage()) {
      -027            return false;
      -028        }
      -029
      -030        Integer permissionOffset = discordPermissionOffsets.get(permission);
      -031        if (permissionOffset == null) {
      -032            return false;
      -033        }
      -034
      -035        return event.getIssuer().getMember().hasPermission(
      -036                Permission.getFromOffset(permissionOffset)
      -037        );
      -038    }
      -039}
      +
      001package co.aikar.commands;
      +002
      +003import net.dv8tion.jda.core.Permission;
      +004
      +005import java.util.HashMap;
      +006import java.util.Locale;
      +007import java.util.Map;
      +008
      +009public class JDACommandPermissionResolver implements CommandPermissionResolver {
      +010    private Map<String, Integer> discordPermissionOffsets;
      +011
      +012    public JDACommandPermissionResolver() {
      +013        discordPermissionOffsets = new HashMap<>();
      +014        for (Permission permission : Permission.values()) {
      +015            discordPermissionOffsets.put(permission.name().toLowerCase(Locale.ENGLISH).replaceAll("_", "-"), permission.getOffset());
      +016        }
      +017    }
      +018
      +019    @Override
      +020    public boolean hasPermission(JDACommandManager manager, JDACommandEvent event, String permission) {
      +021        // Explicitly return true if the issuer is the bot's owner. They are always allowed.
      +022        if (manager.getBotOwnerId() == event.getIssuer().getAuthor().getIdLong()) {
      +023            return true;
      +024        }
      +025
      +026        // Return false on webhook messages, as they cannot have permissions defined.
      +027        if (event.getIssuer().isWebhookMessage()) {
      +028            return false;
      +029        }
      +030
      +031        Integer permissionOffset = discordPermissionOffsets.get(permission);
      +032        if (permissionOffset == null) {
      +033            return false;
      +034        }
      +035
      +036        return event.getIssuer().getMember().hasPermission(
      +037                Permission.getFromOffset(permissionOffset)
      +038        );
      +039    }
      +040}
       
       
       
      @@ -107,5 +109,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDAConditionContext.html b/docs/acf-jda/src-html/co/aikar/commands/JDAConditionContext.html index cb4680b9..7aca3b34 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDAConditionContext.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDAConditionContext.html @@ -1,18 +1,19 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003public class JDAConditionContext extends ConditionContext<JDACommandEvent> {
      -004    JDAConditionContext(JDACommandEvent issuer, String config) {
      -005        super(issuer, config);
      -006    }
      -007}
      +
      001package co.aikar.commands;
      +002
      +003public class JDAConditionContext extends ConditionContext<JDACommandEvent> {
      +004    JDAConditionContext(JDACommandEvent issuer, String config) {
      +005        super(issuer, config);
      +006    }
      +007}
       
       
       
      @@ -75,5 +76,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDAListener.html b/docs/acf-jda/src-html/co/aikar/commands/JDAListener.html index b189129a..ea95381f 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDAListener.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDAListener.html @@ -1,39 +1,40 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import net.dv8tion.jda.core.entities.ChannelType;
      -004import net.dv8tion.jda.core.events.ReadyEvent;
      -005import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      -006import net.dv8tion.jda.core.hooks.ListenerAdapter;
      -007
      -008public class JDAListener extends ListenerAdapter {
      -009
      -010    private final JDACommandManager manager;
      -011
      -012    JDAListener(JDACommandManager manager) {
      -013
      -014        this.manager = manager;
      -015    }
      -016
      -017    @Override
      -018    public void onMessageReceived(MessageReceivedEvent event) {
      -019        if (event.isFromType(ChannelType.TEXT) || event.isFromType(ChannelType.PRIVATE)) {
      -020            this.manager.dispatchEvent(event);
      -021        }
      -022    }
      -023
      -024    @Override
      -025    public void onReady(ReadyEvent event) {
      -026        manager.initializeBotOwner();
      -027    }
      -028}
      +
      001package co.aikar.commands;
      +002
      +003import net.dv8tion.jda.core.entities.ChannelType;
      +004import net.dv8tion.jda.core.events.ReadyEvent;
      +005import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
      +006import net.dv8tion.jda.core.hooks.ListenerAdapter;
      +007
      +008public class JDAListener extends ListenerAdapter {
      +009
      +010    private final JDACommandManager manager;
      +011
      +012    JDAListener(JDACommandManager manager) {
      +013
      +014        this.manager = manager;
      +015    }
      +016
      +017    @Override
      +018    public void onMessageReceived(MessageReceivedEvent event) {
      +019        if (event.isFromType(ChannelType.TEXT) || event.isFromType(ChannelType.PRIVATE)) {
      +020            this.manager.dispatchEvent(event);
      +021        }
      +022    }
      +023
      +024    @Override
      +025    public void onReady(ReadyEvent event) {
      +026        manager.initializeBotOwner();
      +027    }
      +028}
       
       
       
      @@ -96,5 +97,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDALocales.html b/docs/acf-jda/src-html/co/aikar/commands/JDALocales.html index 1b6fbd51..e7b9d2d0 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDALocales.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDALocales.html @@ -1,18 +1,19 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003public class JDALocales extends Locales {
      -004    public JDALocales(CommandManager manager) {
      -005        super(manager);
      -006    }
      -007}
      +
      001package co.aikar.commands;
      +002
      +003public class JDALocales extends Locales {
      +004    public JDALocales(CommandManager manager) {
      +005        super(manager);
      +006    }
      +007}
       
       
       
      @@ -75,5 +76,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDAMessageFormatter.html b/docs/acf-jda/src-html/co/aikar/commands/JDAMessageFormatter.html index bddc06be..8ac198e2 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDAMessageFormatter.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDAMessageFormatter.html @@ -1,25 +1,26 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003public class JDAMessageFormatter extends MessageFormatter<String> {
      -004    public JDAMessageFormatter() {
      -005        // JDA does not support coloring messages outside of embed fields.
      -006        // We pass three empty strings so as to remove color coded messages from appearing.
      -007        super("", "", "");
      -008    }
      -009
      -010    @Override
      -011    String format(String color, String message) {
      -012        return message;
      -013    }
      -014}
      +
      001package co.aikar.commands;
      +002
      +003public class JDAMessageFormatter extends MessageFormatter<String> {
      +004    public JDAMessageFormatter() {
      +005        // JDA does not support coloring messages outside of embed fields.
      +006        // We pass three empty strings so as to remove color coded messages from appearing.
      +007        super("", "", "");
      +008    }
      +009
      +010    @Override
      +011    String format(String color, String message) {
      +012        return message;
      +013    }
      +014}
       
       
       
      @@ -82,5 +83,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDAOptions.html b/docs/acf-jda/src-html/co/aikar/commands/JDAOptions.html index 41385314..faeebaeb 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDAOptions.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDAOptions.html @@ -1,43 +1,44 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import net.dv8tion.jda.core.JDA;
      -004import org.jetbrains.annotations.NotNull;
      -005
      -006public class JDAOptions {
      -007    CommandConfig defaultConfig = new JDACommandConfig();
      -008    CommandConfigProvider configProvider = null;
      -009    CommandPermissionResolver permissionResolver = new JDACommandPermissionResolver();
      -010
      -011    public JDAOptions() {
      -012    }
      -013
      -014    public JDAOptions defaultConfig(@NotNull CommandConfig defaultConfig) {
      -015        this.defaultConfig = defaultConfig;
      -016        return this;
      -017    }
      -018
      -019    public JDAOptions configProvider(@NotNull CommandConfigProvider configProvider) {
      -020        this.configProvider = configProvider;
      -021        return this;
      -022    }
      -023
      -024    public JDAOptions permissionResolver(@NotNull CommandPermissionResolver permissionResolver) {
      -025        this.permissionResolver = permissionResolver;
      -026        return this;
      -027    }
      -028
      -029    public JDACommandManager create(JDA jda) {
      -030        return new JDACommandManager(jda, this);
      -031    }
      -032}
      +
      001package co.aikar.commands;
      +002
      +003import net.dv8tion.jda.core.JDA;
      +004import org.jetbrains.annotations.NotNull;
      +005
      +006public class JDAOptions {
      +007    CommandConfig defaultConfig = new JDACommandConfig();
      +008    CommandConfigProvider configProvider = null;
      +009    CommandPermissionResolver permissionResolver = new JDACommandPermissionResolver();
      +010
      +011    public JDAOptions() {
      +012    }
      +013
      +014    public JDAOptions defaultConfig(@NotNull CommandConfig defaultConfig) {
      +015        this.defaultConfig = defaultConfig;
      +016        return this;
      +017    }
      +018
      +019    public JDAOptions configProvider(@NotNull CommandConfigProvider configProvider) {
      +020        this.configProvider = configProvider;
      +021        return this;
      +022    }
      +023
      +024    public JDAOptions permissionResolver(@NotNull CommandPermissionResolver permissionResolver) {
      +025        this.permissionResolver = permissionResolver;
      +026        return this;
      +027    }
      +028
      +029    public JDACommandManager create(JDA jda) {
      +030        return new JDACommandManager(jda, this);
      +031    }
      +032}
       
       
       
      @@ -100,5 +101,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/JDARootCommand.html b/docs/acf-jda/src-html/co/aikar/commands/JDARootCommand.html index ba1a83ef..5ddb9d3b 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/JDARootCommand.html +++ b/docs/acf-jda/src-html/co/aikar/commands/JDARootCommand.html @@ -1,68 +1,69 @@ - + Source code +
      -
      001package co.aikar.commands;
      -002
      -003import com.google.common.collect.HashMultimap;
      -004import com.google.common.collect.SetMultimap;
      -005
      -006import java.util.ArrayList;
      -007import java.util.List;
      -008
      -009public class JDARootCommand implements RootCommand {
      -010
      -011    private final String name;
      -012    boolean isRegistered = false;
      -013    private JDACommandManager manager;
      -014    private BaseCommand defCommand;
      -015    private SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
      -016    private List<BaseCommand> children = new ArrayList<>();
      -017
      -018    JDARootCommand(JDACommandManager manager, String name) {
      -019        this.manager = manager;
      -020        this.name = name;
      -021    }
      -022
      -023    @Override
      -024
      -025    public void addChild(BaseCommand command) {
      -026        if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) {
      -027            this.defCommand = command;
      -028        }
      -029        addChildShared(this.children, this.subCommands, command);
      -030    }
      -031
      -032    @Override
      -033    public CommandManager getManager() {
      -034        return this.manager;
      -035    }
      -036
      -037    @Override
      -038    public SetMultimap<String, RegisteredCommand> getSubCommands() {
      -039        return this.subCommands;
      -040    }
      -041
      -042    @Override
      -043    public List<BaseCommand> getChildren() {
      -044        return this.children;
      -045    }
      -046
      -047    @Override
      -048    public String getCommandName() {
      -049        return this.name;
      -050    }
      -051
      -052    @Override
      -053    public BaseCommand getDefCommand() {
      -054        return defCommand;
      -055    }
      -056
      -057}
      +
      001package co.aikar.commands;
      +002
      +003import com.google.common.collect.HashMultimap;
      +004import com.google.common.collect.SetMultimap;
      +005
      +006import java.util.ArrayList;
      +007import java.util.List;
      +008
      +009public class JDARootCommand implements RootCommand {
      +010
      +011    private final String name;
      +012    boolean isRegistered = false;
      +013    private JDACommandManager manager;
      +014    private BaseCommand defCommand;
      +015    private SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
      +016    private List<BaseCommand> children = new ArrayList<>();
      +017
      +018    JDARootCommand(JDACommandManager manager, String name) {
      +019        this.manager = manager;
      +020        this.name = name;
      +021    }
      +022
      +023    @Override
      +024
      +025    public void addChild(BaseCommand command) {
      +026        if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) {
      +027            this.defCommand = command;
      +028        }
      +029        addChildShared(this.children, this.subCommands, command);
      +030    }
      +031
      +032    @Override
      +033    public CommandManager getManager() {
      +034        return this.manager;
      +035    }
      +036
      +037    @Override
      +038    public SetMultimap<String, RegisteredCommand> getSubCommands() {
      +039        return this.subCommands;
      +040    }
      +041
      +042    @Override
      +043    public List<BaseCommand> getChildren() {
      +044        return this.children;
      +045    }
      +046
      +047    @Override
      +048    public String getCommandName() {
      +049        return this.name;
      +050    }
      +051
      +052    @Override
      +053    public BaseCommand getDefCommand() {
      +054        return defCommand;
      +055    }
      +056
      +057}
       
       
       
      @@ -125,5 +126,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/annotation/Author.html b/docs/acf-jda/src-html/co/aikar/commands/annotation/Author.html index 434bb6fc..721a96ad 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/annotation/Author.html +++ b/docs/acf-jda/src-html/co/aikar/commands/annotation/Author.html @@ -1,29 +1,30 @@ - + Source code +
      -
      001package co.aikar.commands.annotation;
      -002
      -003import java.lang.annotation.ElementType;
      -004import java.lang.annotation.Retention;
      -005import java.lang.annotation.RetentionPolicy;
      -006import java.lang.annotation.Target;
      -007
      -008/**
      -009 * The {@link Author} annotation is to define whether the parameter should be the author object from the event or
      -010 * parsed from the user's input.
      -011 * <p>
      -012 *      Using this on a User/Member will fetch the author and otherwise it'll parse the input.
      -013 * </p>
      -014 */
      -015@Target(ElementType.PARAMETER)
      -016@Retention(RetentionPolicy.RUNTIME)
      -017public @interface Author {
      -018}
      +
      001package co.aikar.commands.annotation;
      +002
      +003import java.lang.annotation.ElementType;
      +004import java.lang.annotation.Retention;
      +005import java.lang.annotation.RetentionPolicy;
      +006import java.lang.annotation.Target;
      +007
      +008/**
      +009 * The {@link Author} annotation is to define whether the parameter should be the author object from the event or
      +010 * parsed from the user's input.
      +011 * <p>
      +012 *      Using this on a User/Member will fetch the author and otherwise it'll parse the input.
      +013 * </p>
      +014 */
      +015@Target(ElementType.PARAMETER)
      +016@Retention(RetentionPolicy.RUNTIME)
      +017public @interface Author {
      +018}
       
       
       
      @@ -86,5 +87,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/annotation/CrossGuild.html b/docs/acf-jda/src-html/co/aikar/commands/annotation/CrossGuild.html index dacf1d2d..333b99a2 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/annotation/CrossGuild.html +++ b/docs/acf-jda/src-html/co/aikar/commands/annotation/CrossGuild.html @@ -1,30 +1,31 @@ - + Source code +
      -
      001package co.aikar.commands.annotation;
      -002
      -003import java.lang.annotation.ElementType;
      -004import java.lang.annotation.Retention;
      -005import java.lang.annotation.RetentionPolicy;
      -006import java.lang.annotation.Target;
      -007
      -008/**
      -009 * The {@link CrossGuild} annotation is to define whether the parameter should be guild-specific or global.
      -010 * <p>
      -011 *     If a supported parameter is marked with the CrossGuild annotation, the parameter will be filled from
      -012 *     a global perspective (i.e., all of the guilds the bot is connected to). Otherwise, the parameter will
      -013 *     be filled from command input.
      -014 * </p>
      -015 */
      -016@Target(ElementType.PARAMETER)
      -017@Retention(RetentionPolicy.RUNTIME)
      -018public @interface CrossGuild {
      -019}
      +
      001package co.aikar.commands.annotation;
      +002
      +003import java.lang.annotation.ElementType;
      +004import java.lang.annotation.Retention;
      +005import java.lang.annotation.RetentionPolicy;
      +006import java.lang.annotation.Target;
      +007
      +008/**
      +009 * The {@link CrossGuild} annotation is to define whether the parameter should be guild-specific or global.
      +010 * <p>
      +011 *     If a supported parameter is marked with the CrossGuild annotation, the parameter will be filled from
      +012 *     a global perspective (i.e., all of the guilds the bot is connected to). Otherwise, the parameter will
      +013 *     be filled from command input.
      +014 * </p>
      +015 */
      +016@Target(ElementType.PARAMETER)
      +017@Retention(RetentionPolicy.RUNTIME)
      +018public @interface CrossGuild {
      +019}
       
       
       
      @@ -87,5 +88,6 @@
       
       
      +
      diff --git a/docs/acf-jda/src-html/co/aikar/commands/annotation/SelfUser.html b/docs/acf-jda/src-html/co/aikar/commands/annotation/SelfUser.html index ffa9ca9b..12cebfe1 100644 --- a/docs/acf-jda/src-html/co/aikar/commands/annotation/SelfUser.html +++ b/docs/acf-jda/src-html/co/aikar/commands/annotation/SelfUser.html @@ -1,26 +1,27 @@ - + Source code +
      -
      001package co.aikar.commands.annotation;
      -002
      -003import java.lang.annotation.ElementType;
      -004import java.lang.annotation.Retention;
      -005import java.lang.annotation.RetentionPolicy;
      -006import java.lang.annotation.Target;
      -007
      -008/**
      -009 * The {@link SelfUser} annotation is to define whether the parameter should be represented by JDA's user object
      -010 * or if it should be parsed from command input.
      -011 */
      -012@Target(ElementType.PARAMETER)
      -013@Retention(RetentionPolicy.RUNTIME)
      -014public @interface SelfUser {
      -015}
      +
      001package co.aikar.commands.annotation;
      +002
      +003import java.lang.annotation.ElementType;
      +004import java.lang.annotation.Retention;
      +005import java.lang.annotation.RetentionPolicy;
      +006import java.lang.annotation.Target;
      +007
      +008/**
      +009 * The {@link SelfUser} annotation is to define whether the parameter should be represented by JDA's user object
      +010 * or if it should be parsed from command input.
      +011 */
      +012@Target(ElementType.PARAMETER)
      +013@Retention(RetentionPolicy.RUNTIME)
      +014public @interface SelfUser {
      +015}
       
       
       
      @@ -83,5 +84,6 @@
       
       
      +
      diff --git a/docs/acf-jda/stylesheet.css b/docs/acf-jda/stylesheet.css index 98055b22..fa246765 100644 --- a/docs/acf-jda/stylesheet.css +++ b/docs/acf-jda/stylesheet.css @@ -1,35 +1,51 @@ -/* Javadoc style sheet */ -/* -Overall document style -*/ +/* + * Javadoc style sheet + */ @import url('resources/fonts/dejavu.css'); +/* + * Styles for individual HTML elements. + * + * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular + * HTML element throughout the page. + */ + body { background-color:#ffffff; color:#353833; font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; font-size:14px; margin:0; + padding:0; + height:100%; + width:100%; +} +iframe { + margin:0; + padding:0; + height:100%; + width:100%; + overflow-y:scroll; + border:none; } a:link, a:visited { text-decoration:none; color:#4A6782; } -a:hover, a:focus { +a[href]:hover, a[href]:focus { text-decoration:none; color:#bb7a2a; } -a:active { - text-decoration:none; - color:#4A6782; -} a[name] { color:#353833; } -a[name]:hover { - text-decoration:none; - color:#353833; +a[name]:before, a[name]:target, a[id]:before, a[id]:target { + content:""; + display:inline-block; + position:relative; + padding-top:129px; + margin-top:-129px; } pre { font-family:'DejaVu Sans Mono', monospace; @@ -78,9 +94,16 @@ table tr td dt code { sup { font-size:8px; } + /* -Document title and Copyright styles -*/ + * Styles for HTML generated by javadoc. + * + * These are style classes that are used by the standard doclet to generate HTML documentation. + */ + +/* + * Styles for document title and copyright. + */ .clear { clear:both; height:0px; @@ -111,8 +134,8 @@ Document title and Copyright styles font-weight:bold; } /* -Navigation bar styles -*/ + * Styles for navigation bar. + */ .bar { background-color:#4D7A97; color:#FFFFFF; @@ -121,6 +144,15 @@ Navigation bar styles font-size:11px; margin:0; } +.navPadding { + padding-top: 107px; +} +.fixedNav { + position:fixed; + width:100%; + z-index:999; + background-color:#ffffff; +} .topNav { background-color:#4D7A97; color:#FFFFFF; @@ -170,7 +202,22 @@ ul.navList li{ padding: 5px 6px; text-transform:uppercase; } -ul.subNavList li{ +ul.navListSearch { + float:right; + margin:0 0 0 0; + padding:0; +} +ul.navListSearch li { + list-style:none; + float:right; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch li label { + position:relative; + right:-16px; +} +ul.subNavList li { list-style:none; float:left; } @@ -196,21 +243,29 @@ ul.subNavList li{ overflow:hidden; } /* -Page header and footer styles -*/ + * Styles for page header and footer. + */ .header, .footer { clear:both; margin:0 20px; padding:5px 0 0 0; } -.indexHeader { - margin:10px; +.indexNav { position:relative; + font-size:12px; + background-color:#dee3e9; } -.indexHeader span{ - margin-right:15px; +.indexNav ul { + margin-top:0; + padding:5px; } -.indexHeader h1 { +.indexNav ul li { + display:inline; + list-style-type:none; + padding-right:10px; + text-transform:uppercase; +} +.indexNav h1 { font-size:13px; } .title { @@ -232,8 +287,8 @@ Page header and footer styles font-size:13px; } /* -Heading styles -*/ + * Styles for headings. + */ div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { background-color:#dee3e9; border:1px solid #d0d9e0; @@ -254,9 +309,10 @@ ul.blockList li.blockList h2 { padding:0px 0 20px 0; } /* -Page layout container styles -*/ -.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + * Styles for page layout containers. + */ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer, +.allClassesContainer, .allPackagesContainer { clear:both; padding:10px 20px; position:relative; @@ -287,7 +343,7 @@ Page layout container styles .contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { margin:5px 0 10px 0px; font-size:14px; - font-family:'DejaVu Sans Mono',monospace; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } .serializedFormContainer dl.nameValue dt { margin-left:1px; @@ -301,8 +357,11 @@ Page layout container styles display:inline; } /* -List styles -*/ + * Styles for lists. + */ +li.circle { + list-style:circle; +} ul.horizontal li { display:inline; font-size:0.9em; @@ -355,19 +414,22 @@ table tr td dl, table tr td dl dt, table tr td dl dd { margin-bottom:1px; } /* -Table styles -*/ -.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + * Styles for tables. + */ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary, +.requiresSummary, .packagesSummary, .providesSummary, .usesSummary { width:100%; + border-spacing:0; border-left:1px solid #EEE; border-right:1px solid #EEE; border-bottom:1px solid #EEE; } -.overviewSummary, .memberSummary { +.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary { padding:0px; } .overviewSummary caption, .memberSummary caption, .typeSummary caption, -.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption, +.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption { position:relative; text-align:left; background-repeat:no-repeat; @@ -382,17 +444,31 @@ Table styles white-space:pre; } .overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, -.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.constantsSummary caption a:link, .deprecatedSummary caption a:link, +.requiresSummary caption a:link, .packagesSummary caption a:link, .providesSummary caption a:link, +.usesSummary caption a:link, .overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, -.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.requiresSummary caption a:hover, .packagesSummary caption a:hover, .providesSummary caption a:hover, +.usesSummary caption a:hover, .overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, -.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.constantsSummary caption a:active, .deprecatedSummary caption a:active, +.requiresSummary caption a:active, .packagesSummary caption a:active, .providesSummary caption a:active, +.usesSummary caption a:active, .overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, -.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { +.constantsSummary caption a:visited, .deprecatedSummary caption a:visited, +.requiresSummary caption a:visited, .packagesSummary caption a:visited, .providesSummary caption a:visited, +.usesSummary caption a:visited { color:#FFFFFF; } +.useSummary caption a:link, .useSummary caption a:hover, .useSummary caption a:active, +.useSummary caption a:visited { + color:#1f389c; +} .overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, -.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span, +.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span, +.usesSummary caption span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -404,7 +480,8 @@ Table styles border: none; height:16px; } -.memberSummary caption span.activeTableTab span { +.memberSummary caption span.activeTableTab span, .packagesSummary caption span.activeTableTab span, +.overviewSummary caption span.activeTableTab span, .typeSummary caption span.activeTableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -415,7 +492,8 @@ Table styles background-color:#F8981D; height:16px; } -.memberSummary caption span.tableTab span { +.memberSummary caption span.tableTab span, .packagesSummary caption span.tableTab span, +.overviewSummary caption span.tableTab span, .typeSummary caption span.tableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -426,7 +504,10 @@ Table styles background-color:#4D7A97; height:16px; } -.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab, +.packagesSummary caption span.tableTab, .packagesSummary caption span.activeTableTab, +.overviewSummary caption span.tableTab, .overviewSummary caption span.activeTableTab, +.typeSummary caption span.tableTab, .typeSummary caption span.activeTableTab { padding-top:0px; padding-left:0px; padding-right:0px; @@ -435,14 +516,16 @@ Table styles display:inline; } .overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, -.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd, +.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd { display:none; width:5px; position:relative; float:left; background-color:#F8981D; } -.memberSummary .activeTableTab .tabEnd { +.memberSummary .activeTableTab .tabEnd, .packagesSummary .activeTableTab .tabEnd, +.overviewSummary .activeTableTab .tabEnd, .typeSummary .activeTableTab .tabEnd { display:none; width:5px; margin-right:3px; @@ -450,66 +533,88 @@ Table styles float:left; background-color:#F8981D; } -.memberSummary .tableTab .tabEnd { +.memberSummary .tableTab .tabEnd, .packagesSummary .tableTab .tabEnd, +.overviewSummary .tableTab .tabEnd, .typeSummary .tableTab .tabEnd { display:none; width:5px; margin-right:3px; position:relative; background-color:#4D7A97; float:left; - +} +.rowColor th, .altColor th { + font-weight:normal; } .overviewSummary td, .memberSummary td, .typeSummary td, -.useSummary td, .constantsSummary td, .deprecatedSummary td { +.useSummary td, .constantsSummary td, .deprecatedSummary td, +.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td { text-align:left; padding:0px 0px 12px 10px; } -th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, -td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .useSummary th, +.constantsSummary th, .packagesSummary th, td.colFirst, td.colSecond, td.colLast, .useSummary td, +.constantsSummary td { vertical-align:top; padding-right:0px; padding-top:8px; padding-bottom:3px; } -th.colFirst, th.colLast, th.colOne, .constantsSummary th { +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .constantsSummary th, +.packagesSummary th { background:#dee3e9; text-align:left; padding:8px 3px 3px 7px; } td.colFirst, th.colFirst { - white-space:nowrap; font-size:13px; } -td.colLast, th.colLast { +td.colSecond, th.colSecond, td.colLast, th.colConstructorName, th.colDeprecatedItemName, th.colLast { font-size:13px; } -td.colOne, th.colOne { +.constantsSummary th, .packagesSummary th { + font-size:13px; +} +.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst, +.providesSummary td.colLast { + white-space:normal; font-size:13px; } .overviewSummary td.colFirst, .overviewSummary th.colFirst, -.useSummary td.colFirst, .useSummary th.colFirst, -.overviewSummary td.colOne, .overviewSummary th.colOne, +.requiresSummary td.colFirst, .requiresSummary th.colFirst, +.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th, +.usesSummary td.colFirst, .usesSummary th.colFirst, +.providesSummary td.colFirst, .providesSummary th.colFirst, .memberSummary td.colFirst, .memberSummary th.colFirst, -.memberSummary td.colOne, .memberSummary th.colOne, -.typeSummary td.colFirst{ - width:25%; +.memberSummary td.colSecond, .memberSummary th.colSecond, .memberSummary th.colConstructorName, +.typeSummary td.colFirst, .typeSummary th.colFirst { vertical-align:top; } -td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { +.packagesSummary th.colLast, .packagesSummary td.colLast { + white-space:normal; +} +td.colFirst a:link, td.colFirst a:visited, +td.colSecond a:link, td.colSecond a:visited, +th.colFirst a:link, th.colFirst a:visited, +th.colSecond a:link, th.colSecond a:visited, +th.colConstructorName a:link, th.colConstructorName a:visited, +th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited, +.constantValuesContainer td a:link, .constantValuesContainer td a:visited, +.allClassesContainer td a:link, .allClassesContainer td a:visited, +.allPackagesContainer td a:link, .allPackagesContainer td a:visited { font-weight:bold; } .tableSubHeadingColor { background-color:#EEEEFF; } -.altColor { +.altColor, .altColor th { background-color:#FFFFFF; } -.rowColor { +.rowColor, .rowColor th { background-color:#EEEEEF; } /* -Content styles -*/ + * Styles for contents. + */ .description pre { margin-top:0; } @@ -520,27 +625,22 @@ Content styles .docSummary { padding:0; } - ul.blockList ul.blockList ul.blockList li.blockList h3 { font-style:normal; } - div.block { font-size:14px; font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } - td.colLast div { padding-top:0px; } - - td.colLast a { padding-bottom:3px; } /* -Formatting effect styles -*/ + * Styles for formatting effect. + */ .sourceLineNo { color:green; padding:0 30px 0 0; @@ -555,20 +655,252 @@ h1.hidden { margin:3px 10px 2px 0px; color:#474747; } -.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { +.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink, +.moduleLabelInPackage, .moduleLabelInType, .overrideSpecifyLabel, .packageLabelInType, +.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, +.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { font-weight:bold; } .deprecationComment, .emphasizedPhrase, .interfaceName { font-style:italic; } - -div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +.deprecationBlock { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +div.block div.deprecationComment, div.block div.block span.emphasizedPhrase, div.block div.block span.interfaceName { font-style:normal; } - -div.contentContainer ul.blockList li.blockList h2{ +div.contentContainer ul.blockList li.blockList h2 { padding-bottom:0px; } +/* + * Styles for IFRAME. + */ +.mainContainer { + margin:0 auto; + padding:0; + height:100%; + width:100%; + position:fixed; + top:0; + left:0; +} +.leftContainer { + height:100%; + position:fixed; + width:320px; +} +.leftTop { + position:relative; + float:left; + width:315px; + top:0; + left:0; + height:30%; + border-right:6px solid #ccc; + border-bottom:6px solid #ccc; +} +.leftBottom { + position:relative; + float:left; + width:315px; + bottom:0; + left:0; + height:70%; + border-right:6px solid #ccc; + border-top:1px solid #000; +} +.rightContainer { + position:absolute; + left:320px; + top:0; + bottom:0; + height:100%; + right:0; + border-left:1px solid #000; +} +.rightIframe { + margin:0; + padding:0; + height:100%; + right:30px; + width:100%; + overflow:visible; + margin-bottom:30px; +} +/* + * Styles specific to HTML5 elements. + */ +main, nav, header, footer, section { + display:block; +} +/* + * Styles for javadoc search. + */ +.ui-autocomplete-category { + font-weight:bold; + font-size:15px; + padding:7px 0 7px 3px; + background-color:#4D7A97; + color:#FFFFFF; +} +.resultItem { + font-size:13px; +} +.ui-autocomplete { + max-height:85%; + max-width:65%; + overflow-y:scroll; + overflow-x:scroll; + white-space:nowrap; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); +} +ul.ui-autocomplete { + position:fixed; + z-index:999999; +} +ul.ui-autocomplete li { + float:left; + clear:both; + width:100%; +} +.resultHighlight { + font-weight:bold; +} +#search { + background-image:url('resources/glass.png'); + background-size:13px; + background-repeat:no-repeat; + background-position:2px 3px; + padding-left:20px; + position:relative; + right:-18px; +} +#reset { + background-color: rgb(255,255,255); + background-image:url('resources/x.png'); + background-position:center; + background-repeat:no-repeat; + background-size:12px; + border:0 none; + width:16px; + height:17px; + position:relative; + left:-4px; + top:-4px; + font-size:0px; +} +.watermark { + color:#545454; +} +.searchTagDescResult { + font-style:italic; + font-size:11px; +} +.searchTagHolderResult { + font-style:italic; + font-size:12px; +} +.searchTagResult:before, .searchTagResult:target { + color:red; +} +.moduleGraph span { + display:none; + position:absolute; +} +.moduleGraph:hover span { + display:block; + margin: -100px 0 0 100px; + z-index: 1; +} +.methodSignature { + white-space:normal; +} + +/* + * Styles for user-provided tables. + * + * borderless: + * No borders, vertical margins, styled caption. + * This style is provided for use with existing doc comments. + * In general, borderless tables should not be used for layout purposes. + * + * plain: + * Plain borders around table and cells, vertical margins, styled caption. + * Best for small tables or for complex tables for tables with cells that span + * rows and columns, when the "striped" style does not work well. + * + * striped: + * Borders around the table and vertical borders between cells, striped rows, + * vertical margins, styled caption. + * Best for tables that have a header row, and a body containing a series of simple rows. + */ + +table.borderless, +table.plain, +table.striped { + margin-top: 10px; + margin-bottom: 10px; +} +table.borderless > caption, +table.plain > caption, +table.striped > caption { + font-weight: bold; + font-size: smaller; +} +table.borderless th, table.borderless td, +table.plain th, table.plain td, +table.striped th, table.striped td { + padding: 2px 5px; +} +table.borderless, +table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, +table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { + border: none; +} +table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { + background-color: transparent; +} +table.plain { + border-collapse: collapse; + border: 1px solid black; +} +table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { + background-color: transparent; +} +table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, +table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { + border: 1px solid black; +} +table.striped { + border-collapse: collapse; + border: 1px solid black; +} +table.striped > thead { + background-color: #E3E3E3; +} +table.striped > thead > tr > th, table.striped > thead > tr > td { + border: 1px solid black; +} +table.striped > tbody > tr:nth-child(even) { + background-color: #EEE +} +table.striped > tbody > tr:nth-child(odd) { + background-color: #FFF +} +table.striped > tbody > tr > th, table.striped > tbody > tr > td { + border-left: 1px solid black; + border-right: 1px solid black; +} +table.striped > tbody > tr > th { + font-weight: normal; +} diff --git a/docs/acf-jda/type-search-index.js b/docs/acf-jda/type-search-index.js new file mode 100644 index 00000000..8821b5a9 --- /dev/null +++ b/docs/acf-jda/type-search-index.js @@ -0,0 +1 @@ +typeSearchIndex = [{"l":"All Classes","url":"allclasses-index.html"},{"p":"co.aikar.commands.annotation","l":"Author"},{"p":"co.aikar.commands","l":"CommandConfig"},{"p":"co.aikar.commands","l":"CommandConfigProvider"},{"p":"co.aikar.commands","l":"CommandPermissionResolver"},{"p":"co.aikar.commands.annotation","l":"CrossGuild"},{"p":"co.aikar.commands","l":"JDACommandCompletions"},{"p":"co.aikar.commands","l":"JDACommandConfig"},{"p":"co.aikar.commands","l":"JDACommandContexts"},{"p":"co.aikar.commands","l":"JDACommandEvent"},{"p":"co.aikar.commands","l":"JDACommandExecutionContext"},{"p":"co.aikar.commands","l":"JDACommandManager"},{"p":"co.aikar.commands","l":"JDACommandPermissionResolver"},{"p":"co.aikar.commands","l":"JDAConditionContext"},{"p":"co.aikar.commands","l":"JDAListener"},{"p":"co.aikar.commands","l":"JDALocales"},{"p":"co.aikar.commands","l":"JDAMessageFormatter"},{"p":"co.aikar.commands","l":"JDAOptions"},{"p":"co.aikar.commands","l":"JDARootCommand"},{"p":"co.aikar.commands.annotation","l":"SelfUser"}] \ No newline at end of file diff --git a/docs/acf-jda/type-search-index.zip b/docs/acf-jda/type-search-index.zip new file mode 100644 index 00000000..8acbe735 Binary files /dev/null and b/docs/acf-jda/type-search-index.zip differ diff --git a/docs/acf-paper/allclasses-index.html b/docs/acf-paper/allclasses-index.html new file mode 100644 index 00000000..e4c714ff --- /dev/null +++ b/docs/acf-paper/allclasses-index.html @@ -0,0 +1,169 @@ + + + + + +All Classes (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
      + +
      +
      +
      +

      All Classes

      +
      +
      + +
      +
      +
      + +

      Copyright © 2020. All rights reserved.

      +
      + + diff --git a/docs/acf-paper/allclasses.html b/docs/acf-paper/allclasses.html new file mode 100644 index 00000000..0a73f51e --- /dev/null +++ b/docs/acf-paper/allclasses.html @@ -0,0 +1,30 @@ + + + + + +All Classes (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + +

      All Classes

      +
      + +
      + + diff --git a/docs/acf-paper/allpackages-index.html b/docs/acf-paper/allpackages-index.html new file mode 100644 index 00000000..b6bca2e1 --- /dev/null +++ b/docs/acf-paper/allpackages-index.html @@ -0,0 +1,163 @@ + + + + + +All Packages (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
      + +
      +
      +
      +

      All Packages

      +
      +
      +
        +
      • + + + + + + + + + + + + +
        Package Summary 
        PackageDescription
        co.aikar.commands 
        +
      • +
      +
      +
      +
      + +

      Copyright © 2020. All rights reserved.

      +
      + + diff --git a/docs/acf-paper/co/aikar/commands/PaperCommandCompletions.html b/docs/acf-paper/co/aikar/commands/PaperCommandCompletions.html index ecf3569b..644fee4c 100644 --- a/docs/acf-paper/co/aikar/commands/PaperCommandCompletions.html +++ b/docs/acf-paper/co/aikar/commands/PaperCommandCompletions.html @@ -1,12 +1,21 @@ - + - PaperCommandCompletions (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class PaperCommandCompletions

      @@ -180,37 +211,42 @@ extends co.aikar.commands.BukkitCommandCompletions
      + + diff --git a/docs/acf-paper/co/aikar/commands/PaperCommandContexts.html b/docs/acf-paper/co/aikar/commands/PaperCommandContexts.html index b9680406..e9800b50 100644 --- a/docs/acf-paper/co/aikar/commands/PaperCommandContexts.html +++ b/docs/acf-paper/co/aikar/commands/PaperCommandContexts.html @@ -1,12 +1,21 @@ - + - PaperCommandContexts (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class PaperCommandContexts

      @@ -180,37 +211,42 @@ extends co.aikar.commands.BukkitCommandContexts +
      + diff --git a/docs/acf-paper/co/aikar/commands/PaperCommandManager.html b/docs/acf-paper/co/aikar/commands/PaperCommandManager.html index 21d016af..810bc3c8 100644 --- a/docs/acf-paper/co/aikar/commands/PaperCommandManager.html +++ b/docs/acf-paper/co/aikar/commands/PaperCommandManager.html @@ -1,12 +1,21 @@ - + - PaperCommandManager (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      -
      co.aikar.commands
      +

      Class PaperCommandManager

        -
      • java.lang.Object
      • +
      • java.lang.Object
        • -
        • co.aikar.commands.CommandManager<org.bukkit.command.CommandSender,co.aikar.commands.BukkitCommandIssuer,org.bukkit.ChatColor,co.aikar.commands.BukkitMessageFormatter,co.aikar.commands.BukkitCommandExecutionContext,co.aikar.commands.BukkitConditionContext>
        • +
        • co.aikar.commands.CommandManager<org.bukkit.command.CommandSender,​co.aikar.commands.BukkitCommandIssuer,​org.bukkit.ChatColor,​co.aikar.commands.BukkitMessageFormatter,​co.aikar.commands.BukkitCommandExecutionContext,​co.aikar.commands.BukkitConditionContext>
          • co.aikar.commands.BukkitCommandManager
          • @@ -116,8 +140,7 @@ var activeTableTab = "activeTableTab"; @@ -126,20 +149,21 @@ extends co.aikar.commands.BukkitCommandManager
            • +
                -
              • +
              • Field Summary

                  -
                • +
                • Fields inherited from class co.aikar.commands.BukkitCommandManager

                  autoDetectFromClient, completions, contexts, knownCommands, locales, mcMinorVersion, mcPatchVersion, plugin, registeredCommands
                  -
                • +
                • Fields inherited from class co.aikar.commands.CommandManager

                  @@ -147,67 +171,77 @@ extends co.aikar.commands.BukkitCommandManager
              +
              +
                -
              • +
              • Constructor Summary

                - +
                - + + - + +
                Constructors 
                Constructor and DescriptionConstructorDescription
                PaperCommandManager(org.bukkit.plugin.Plugin plugin) PaperCommandManager​(org.bukkit.plugin.Plugin plugin) 
              +
              +
                -
              • +
              • Method Summary

                - +
                - + + - + + - + +
                All Methods Instance Methods Concrete Methods 
                Modifier and TypeMethod and DescriptionMethodDescription
                co.aikar.commands.CommandCompletions<co.aikar.commands.BukkitCommandCompletionContext>getCommandCompletions() getCommandCompletions() 
                co.aikar.commands.CommandContexts<co.aikar.commands.BukkitCommandExecutionContext>getCommandContexts() getCommandContexts() 
                  -
                • +
                • Methods inherited from class co.aikar.commands.BukkitCommandManager

                  createCommandContext, createCompletionContext, createConditionContext, createRegisteredCommand, createRootCommand, getCommandIssuer, getCommandPrefix, getLocales, getPlugin, getRegisteredRootCommands, getTimings, handleUncaughtException, hasRegisteredCommands, isCommandIssuer, log, registerCommand, registerCommand, setPlayerLocale, unregisterCommand, unregisterCommand, unregisterCommands, usePerIssuerLocale
                  -
                • +
                • Methods inherited from class co.aikar.commands.CommandManager

                  addSupportedLanguage, enableUnstableAPI, formatMessage, generateCommandHelp, generateCommandHelp, generateCommandHelp, generateCommandHelp, getCommandConditions, getCommandReplacements, getCurrentCommandIssuer, getCurrentCommandManager, getCurrentCommandOperationContext, getDefaultExceptionHandler, getDefaultFormatter, getDefaultHelpPerPage, getFormat, getHelpFormatter, getIssuerLocale, getRootCommand, getSupportedLanguages, hasPermission, hasPermission, isLoggingUnhandledExceptions, log, notifyLocaleChange, obtainRootCommand, onLocaleChange, registerDependency, registerDependency, sendMessage, sendMessage, setDefaultExceptionHandler, setDefaultExceptionHandler, setDefaultFormatter, setDefaultHelpPerPage, setFormat, setFormat, setFormat, setHelpFormatter, setIssuerLocale, usePerIssuerLocale, usingPerIssuerLocale
              +
      @@ -215,48 +249,51 @@ extends co.aikar.commands.BukkitCommandManager
      • +
        +
        +
          -
        • +
        • Method Detail

          - +
          • getCommandContexts

            -
            public co.aikar.commands.CommandContexts<co.aikar.commands.BukkitCommandExecutionContext> getCommandContexts()
            +
            public co.aikar.commands.CommandContexts<co.aikar.commands.BukkitCommandExecutionContext> getCommandContexts()
            Overrides:
            getCommandContexts in class co.aikar.commands.BukkitCommandManager
          - +
          • getCommandCompletions

            -
            public co.aikar.commands.CommandCompletions<co.aikar.commands.BukkitCommandCompletionContext> getCommandCompletions()
            +
            public co.aikar.commands.CommandCompletions<co.aikar.commands.BukkitCommandCompletionContext> getCommandCompletions()
            Overrides:
            getCommandCompletions in class co.aikar.commands.BukkitCommandManager
            @@ -265,21 +302,25 @@ extends co.aikar.commands.BukkitCommandManager
        +
      +
      + diff --git a/docs/acf-paper/co/aikar/commands/class-use/PaperCommandCompletions.html b/docs/acf-paper/co/aikar/commands/class-use/PaperCommandCompletions.html index da84fe7c..f3b12848 100644 --- a/docs/acf-paper/co/aikar/commands/class-use/PaperCommandCompletions.html +++ b/docs/acf-paper/co/aikar/commands/class-use/PaperCommandCompletions.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.PaperCommandCompletions (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.PaperCommandCompletions

      No usage of co.aikar.commands.PaperCommandCompletions
      +
      + diff --git a/docs/acf-paper/co/aikar/commands/class-use/PaperCommandContexts.html b/docs/acf-paper/co/aikar/commands/class-use/PaperCommandContexts.html index d22bfeeb..89c68033 100644 --- a/docs/acf-paper/co/aikar/commands/class-use/PaperCommandContexts.html +++ b/docs/acf-paper/co/aikar/commands/class-use/PaperCommandContexts.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.PaperCommandContexts (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.PaperCommandContexts

      No usage of co.aikar.commands.PaperCommandContexts
      +
      + diff --git a/docs/acf-paper/co/aikar/commands/class-use/PaperCommandManager.html b/docs/acf-paper/co/aikar/commands/class-use/PaperCommandManager.html index 20e19c01..14d9a880 100644 --- a/docs/acf-paper/co/aikar/commands/class-use/PaperCommandManager.html +++ b/docs/acf-paper/co/aikar/commands/class-use/PaperCommandManager.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.PaperCommandManager (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Uses of Class
      co.aikar.commands.PaperCommandManager

      @@ -74,40 +98,48 @@ +
      + diff --git a/docs/acf-paper/co/aikar/commands/package-summary.html b/docs/acf-paper/co/aikar/commands/package-summary.html index e6ad0806..04c08516 100644 --- a/docs/acf-paper/co/aikar/commands/package-summary.html +++ b/docs/acf-paper/co/aikar/commands/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Package co.aikar.commands

      • - +
        @@ -81,15 +105,15 @@ - + - + - + @@ -97,16 +121,19 @@ + + diff --git a/docs/acf-paper/co/aikar/commands/package-tree.html b/docs/acf-paper/co/aikar/commands/package-tree.html index 1238135e..60d02f31 100644 --- a/docs/acf-paper/co/aikar/commands/package-tree.html +++ b/docs/acf-paper/co/aikar/commands/package-tree.html @@ -1,12 +1,21 @@ - + -co.aikar.commands Class Hierarchy (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
        + +
        +

        Hierarchy For Package co.aikar.commands

        +

        Class Hierarchy

          -
        • java.lang.Object +
        • java.lang.Object
            -
          • co.aikar.commands.CommandCompletions<C> +
          • co.aikar.commands.CommandCompletions<C>
          • -
          • co.aikar.commands.CommandContexts<R> +
          • co.aikar.commands.CommandContexts<R>
          • -
          • co.aikar.commands.CommandManager<IT,I,FT,MF,CEC,CC> +
          • co.aikar.commands.CommandManager<IT,​I,​FT,​MF,​CEC,​CC> @@ -105,17 +130,21 @@
        +
        +
        + diff --git a/docs/acf-paper/co/aikar/commands/package-use.html b/docs/acf-paper/co/aikar/commands/package-use.html index 2b0356e9..85c6e053 100644 --- a/docs/acf-paper/co/aikar/commands/package-use.html +++ b/docs/acf-paper/co/aikar/commands/package-use.html @@ -1,12 +1,21 @@ - + -Uses of Package co.aikar.commands (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
        + +
        +

        Uses of Package
        co.aikar.commands

        Class Summary 
        Class
        PaperCommandCompletionsPaperCommandCompletions  
        PaperCommandContextsPaperCommandContexts  
        PaperCommandManagerPaperCommandManager  
        - +
        Classes in co.aikar.commands used by co.aikar.commands 
        + - + + - + +
        Classes in co.aikar.commands used by co.aikar.commands 
        Class and DescriptionClassDescription
        PaperCommandManager PaperCommandManager 
      +
      + diff --git a/docs/acf-paper/constant-values.html b/docs/acf-paper/constant-values.html index 1e66f834..0e81a7ba 100644 --- a/docs/acf-paper/constant-values.html +++ b/docs/acf-paper/constant-values.html @@ -1,12 +1,21 @@ - + - Constant Field Values (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Constant Field Values

      +

      Contents

      +
      +
      + diff --git a/docs/acf-paper/deprecated-list.html b/docs/acf-paper/deprecated-list.html index dd639959..75a31236 100644 --- a/docs/acf-paper/deprecated-list.html +++ b/docs/acf-paper/deprecated-list.html @@ -1,12 +1,21 @@ - + - Deprecated List (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Deprecated API

      Contents

      +
      + diff --git a/docs/acf-paper/element-list b/docs/acf-paper/element-list new file mode 100644 index 00000000..0886d25c --- /dev/null +++ b/docs/acf-paper/element-list @@ -0,0 +1 @@ +co.aikar.commands diff --git a/docs/acf-paper/index-all.html b/docs/acf-paper/index-all.html index 665f283d..5ff11af8 100644 --- a/docs/acf-paper/index-all.html +++ b/docs/acf-paper/index-all.html @@ -1,12 +1,21 @@ - + - Index (ACF (Paper) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +
      +
      C G P 
      All Classes All Packages

      C

      @@ -75,41 +99,44 @@
      co.aikar.commands - package co.aikar.commands
       
      - +

      G

      -
      getCommandCompletions() - Method in class co.aikar.commands.PaperCommandManager
      +
      getCommandCompletions() - Method in class co.aikar.commands.PaperCommandManager
       
      -
      getCommandContexts() - Method in class co.aikar.commands.PaperCommandManager
      +
      getCommandContexts() - Method in class co.aikar.commands.PaperCommandManager
       
      - +

      P

      PaperCommandCompletions - Class in co.aikar.commands
       
      -
      PaperCommandCompletions(PaperCommandManager) - Constructor for class co.aikar.commands.PaperCommandCompletions
      +
      PaperCommandCompletions(PaperCommandManager) - Constructor for class co.aikar.commands.PaperCommandCompletions
       
      PaperCommandContexts - Class in co.aikar.commands
       
      -
      PaperCommandContexts(PaperCommandManager) - Constructor for class co.aikar.commands.PaperCommandContexts
      +
      PaperCommandContexts(PaperCommandManager) - Constructor for class co.aikar.commands.PaperCommandContexts
       
      PaperCommandManager - Class in co.aikar.commands
       
      -
      PaperCommandManager(Plugin) - Constructor for class co.aikar.commands.PaperCommandManager
      +
      PaperCommandManager(Plugin) - Constructor for class co.aikar.commands.PaperCommandManager
       
      -C G P 
      +C G P 
      All Classes All Packages +
      + diff --git a/docs/acf-paper/index.html b/docs/acf-paper/index.html index 9401b7e6..5fa4bcfb 100644 --- a/docs/acf-paper/index.html +++ b/docs/acf-paper/index.html @@ -1,73 +1,23 @@ - + - - + ACF (Paper) 0.5.0-SNAPSHOT API - - - - - - +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<script type="text/javascript">window.location.replace('co/aikar/commands/package-summary.html')</script> <noscript> -<div>JavaScript is disabled on your browser.</div> +<meta http-equiv="Refresh" content="0;co/aikar/commands/package-summary.html"> </noscript> -<h2>Frame Alert</h2> -<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="co/aikar/commands/package-summary.html">Non-frame version</a>.</p> - - + + + + +
      + +

      co/aikar/commands/package-summary.html

      +
      + diff --git a/docs/acf-paper/jquery/external/jquery/jquery.js b/docs/acf-paper/jquery/external/jquery/jquery.js new file mode 100644 index 00000000..9b5206bc --- /dev/null +++ b/docs/acf-paper/jquery/external/jquery/jquery.js @@ -0,0 +1,10364 @@ +/*! + * jQuery JavaScript Library v3.3.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2018-01-20T17:24Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + + + + var preservedScriptAttributes = { + type: true, + src: true, + noModule: true + }; + + function DOMEval( code, doc, node ) { + doc = doc || document; + + var i, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + if ( node[ i ] ) { + script[ i ] = node[ i ]; + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.3.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && Array.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( nodeName( elem, "iframe" ) ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting
    • ", "
      " ], + col: [ 2, "", "
      " ], + tr: [ 2, "", "
      " ], + td: [ 3, "", "
      " ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + div.style.position = "absolute"; + scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a property mapped along what jQuery.cssProps suggests or to +// a vendor prefixed property. +function finalPropName( name ) { + var ret = jQuery.cssProps[ name ]; + if ( !ret ) { + ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + } + return ret; +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + ) ); + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + val = curCSS( elem, dimension, styles ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox; + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = valueIsBorderBox && + ( support.boxSizingReliable() || val === elem.style[ dimension ] ); + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + if ( val === "auto" || + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { + + val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; + + // offsetWidth/offsetHeight provide border-box values + valueIsBorderBox = true; + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra && boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ); + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && support.scrollboxSize() === styles.position ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = Date.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "\r\n"; + +// inject VBScript +document.write(IEBinaryToArray_ByteStr_Script); + +global.JSZipUtils._getBinaryFromXHR = function (xhr) { + var binary = xhr.responseBody; + var byteMapping = {}; + for ( var i = 0; i < 256; i++ ) { + for ( var j = 0; j < 256; j++ ) { + byteMapping[ String.fromCharCode( i + (j << 8) ) ] = + String.fromCharCode(i) + String.fromCharCode(j); + } + } + var rawBytes = IEBinaryToArray_ByteStr(binary); + var lastChr = IEBinaryToArray_ByteStr_Last(binary); + return rawBytes.replace(/[\s\S]/g, function( match ) { + return byteMapping[match]; + }) + lastChr; +}; + +// enforcing Stuk's coding style +// vim: set shiftwidth=4 softtabstop=4: + +},{}]},{},[1]) +; diff --git a/docs/acf-paper/jquery/jszip-utils/dist/jszip-utils-ie.min.js b/docs/acf-paper/jquery/jszip-utils/dist/jszip-utils-ie.min.js new file mode 100644 index 00000000..93d8bc8e --- /dev/null +++ b/docs/acf-paper/jquery/jszip-utils/dist/jszip-utils-ie.min.js @@ -0,0 +1,10 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); diff --git a/docs/acf-paper/jquery/jszip-utils/dist/jszip-utils.js b/docs/acf-paper/jquery/jszip-utils/dist/jszip-utils.js new file mode 100644 index 00000000..775895ec --- /dev/null +++ b/docs/acf-paper/jquery/jszip-utils/dist/jszip-utils.js @@ -0,0 +1,118 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ + +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64; + enc4 = remainingBytes > 2 ? (chr3 & 63) : 64; + + output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4)); + + } + + return output.join(""); +}; + +// public method for decoding +exports.decode = function(input) { + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0, resultIndex = 0; + + var dataUrlPrefix = "data:"; + + if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) { + // This is a common error: people give a data url + // (data:image/png;base64,iVBOR...) with a {base64: true} and + // wonders why things don't work. + // We can detect that the string input looks like a data url but we + // *can't* be sure it is one: removing everything up to the comma would + // be too dangerous. + throw new Error("Invalid base64 input, it looks like a data url."); + } + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + var totalLength = input.length * 3 / 4; + if(input.charAt(input.length - 1) === _keyStr.charAt(64)) { + totalLength--; + } + if(input.charAt(input.length - 2) === _keyStr.charAt(64)) { + totalLength--; + } + if (totalLength % 1 !== 0) { + // totalLength is not an integer, the length does not match a valid + // base64 content. That can happen if: + // - the input is not a base64 content + // - the input is *almost* a base64 content, with a extra chars at the + // beginning or at the end + // - the input uses a base64 variant (base64url for example) + throw new Error("Invalid base64 input, bad content length."); + } + var output; + if (support.uint8array) { + output = new Uint8Array(totalLength|0); + } else { + output = new Array(totalLength|0); + } + + while (i < input.length) { + + enc1 = _keyStr.indexOf(input.charAt(i++)); + enc2 = _keyStr.indexOf(input.charAt(i++)); + enc3 = _keyStr.indexOf(input.charAt(i++)); + enc4 = _keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output[resultIndex++] = chr1; + + if (enc3 !== 64) { + output[resultIndex++] = chr2; + } + if (enc4 !== 64) { + output[resultIndex++] = chr3; + } + + } + + return output; +}; + +},{"./support":30,"./utils":32}],2:[function(require,module,exports){ +'use strict'; + +var external = require("./external"); +var DataWorker = require('./stream/DataWorker'); +var DataLengthProbe = require('./stream/DataLengthProbe'); +var Crc32Probe = require('./stream/Crc32Probe'); +var DataLengthProbe = require('./stream/DataLengthProbe'); + +/** + * Represent a compressed object, with everything needed to decompress it. + * @constructor + * @param {number} compressedSize the size of the data compressed. + * @param {number} uncompressedSize the size of the data after decompression. + * @param {number} crc32 the crc32 of the decompressed file. + * @param {object} compression the type of compression, see lib/compressions.js. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data. + */ +function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) { + this.compressedSize = compressedSize; + this.uncompressedSize = uncompressedSize; + this.crc32 = crc32; + this.compression = compression; + this.compressedContent = data; +} + +CompressedObject.prototype = { + /** + * Create a worker to get the uncompressed content. + * @return {GenericWorker} the worker. + */ + getContentWorker : function () { + var worker = new DataWorker(external.Promise.resolve(this.compressedContent)) + .pipe(this.compression.uncompressWorker()) + .pipe(new DataLengthProbe("data_length")); + + var that = this; + worker.on("end", function () { + if(this.streamInfo['data_length'] !== that.uncompressedSize) { + throw new Error("Bug : uncompressed data size mismatch"); + } + }); + return worker; + }, + /** + * Create a worker to get the compressed content. + * @return {GenericWorker} the worker. + */ + getCompressedWorker : function () { + return new DataWorker(external.Promise.resolve(this.compressedContent)) + .withStreamInfo("compressedSize", this.compressedSize) + .withStreamInfo("uncompressedSize", this.uncompressedSize) + .withStreamInfo("crc32", this.crc32) + .withStreamInfo("compression", this.compression) + ; + } +}; + +/** + * Chain the given worker with other workers to compress the content with the + * given compresion. + * @param {GenericWorker} uncompressedWorker the worker to pipe. + * @param {Object} compression the compression object. + * @param {Object} compressionOptions the options to use when compressing. + * @return {GenericWorker} the new worker compressing the content. + */ +CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions) { + return uncompressedWorker + .pipe(new Crc32Probe()) + .pipe(new DataLengthProbe("uncompressedSize")) + .pipe(compression.compressWorker(compressionOptions)) + .pipe(new DataLengthProbe("compressedSize")) + .withStreamInfo("compression", compression); +}; + +module.exports = CompressedObject; + +},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require("./stream/GenericWorker"); + +exports.STORE = { + magic: "\x00\x00", + compressWorker : function (compressionOptions) { + return new GenericWorker("STORE compression"); + }, + uncompressWorker : function () { + return new GenericWorker("STORE decompression"); + } +}; +exports.DEFLATE = require('./flate'); + +},{"./flate":7,"./stream/GenericWorker":28}],4:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); + +/** + * The following functions come from pako, from pako/lib/zlib/crc32.js + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +// That's all for the pako functions. + +/** + * Compute the crc32 of a string. + * This is almost the same as the function crc32, but for strings. Using the + * same function for the two use cases leads to horrible performances. + * @param {Number} crc the starting value of the crc. + * @param {String} str the string to use. + * @param {Number} len the length of the string. + * @param {Number} pos the starting position for the crc32 computation. + * @return {Number} the computed crc32. + */ +function crc32str(crc, str, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +module.exports = function crc32wrapper(input, crc) { + if (typeof input === "undefined" || !input.length) { + return 0; + } + + var isArray = utils.getTypeOf(input) !== "string"; + + if(isArray) { + return crc32(crc|0, input, input.length, 0); + } else { + return crc32str(crc|0, input, input.length, 0); + } +}; + +},{"./utils":32}],5:[function(require,module,exports){ +'use strict'; +exports.base64 = false; +exports.binary = false; +exports.dir = false; +exports.createFolders = true; +exports.date = null; +exports.compression = null; +exports.compressionOptions = null; +exports.comment = null; +exports.unixPermissions = null; +exports.dosPermissions = null; + +},{}],6:[function(require,module,exports){ +/* global Promise */ +'use strict'; + +// load the global object first: +// - it should be better integrated in the system (unhandledRejection in node) +// - the environment may have a custom Promise implementation (see zone.js) +var ES6Promise = null; +if (typeof Promise !== "undefined") { + ES6Promise = Promise; +} else { + ES6Promise = require("lie"); +} + +/** + * Let the user use/change some implementations. + */ +module.exports = { + Promise: ES6Promise +}; + +},{"lie":58}],7:[function(require,module,exports){ +'use strict'; +var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); + +var pako = require("pako"); +var utils = require("./utils"); +var GenericWorker = require("./stream/GenericWorker"); + +var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array"; + +exports.magic = "\x08\x00"; + +/** + * Create a worker that uses pako to inflate/deflate. + * @constructor + * @param {String} action the name of the pako function to call : either "Deflate" or "Inflate". + * @param {Object} options the options to use when (de)compressing. + */ +function FlateWorker(action, options) { + GenericWorker.call(this, "FlateWorker/" + action); + + this._pako = null; + this._pakoAction = action; + this._pakoOptions = options; + // the `meta` object from the last chunk received + // this allow this worker to pass around metadata + this.meta = {}; +} + +utils.inherits(FlateWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +FlateWorker.prototype.processChunk = function (chunk) { + this.meta = chunk.meta; + if (this._pako === null) { + this._createPako(); + } + this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false); +}; + +/** + * @see GenericWorker.flush + */ +FlateWorker.prototype.flush = function () { + GenericWorker.prototype.flush.call(this); + if (this._pako === null) { + this._createPako(); + } + this._pako.push([], true); +}; +/** + * @see GenericWorker.cleanUp + */ +FlateWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this._pako = null; +}; + +/** + * Create the _pako object. + * TODO: lazy-loading this object isn't the best solution but it's the + * quickest. The best solution is to lazy-load the worker list. See also the + * issue #446. + */ +FlateWorker.prototype._createPako = function () { + this._pako = new pako[this._pakoAction]({ + raw: true, + level: this._pakoOptions.level || -1 // default compression + }); + var self = this; + this._pako.onData = function(data) { + self.push({ + data : data, + meta : self.meta + }); + }; +}; + +exports.compressWorker = function (compressionOptions) { + return new FlateWorker("Deflate", compressionOptions); +}; +exports.uncompressWorker = function () { + return new FlateWorker("Inflate", {}); +}; + +},{"./stream/GenericWorker":28,"./utils":32,"pako":59}],8:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); +var utf8 = require('../utf8'); +var crc32 = require('../crc32'); +var signature = require('../signature'); + +/** + * Transform an integer into a string in hexadecimal. + * @private + * @param {number} dec the number to convert. + * @param {number} bytes the number of bytes to generate. + * @returns {string} the result. + */ +var decToHex = function(dec, bytes) { + var hex = "", i; + for (i = 0; i < bytes; i++) { + hex += String.fromCharCode(dec & 0xff); + dec = dec >>> 8; + } + return hex; +}; + +/** + * Generate the UNIX part of the external file attributes. + * @param {Object} unixPermissions the unix permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : + * + * TTTTsstrwxrwxrwx0000000000ADVSHR + * ^^^^____________________________ file type, see zipinfo.c (UNX_*) + * ^^^_________________________ setuid, setgid, sticky + * ^^^^^^^^^________________ permissions + * ^^^^^^^^^^______ not used ? + * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only + */ +var generateUnixExternalFileAttr = function (unixPermissions, isDir) { + + var result = unixPermissions; + if (!unixPermissions) { + // I can't use octal values in strict mode, hence the hexa. + // 040775 => 0x41fd + // 0100664 => 0x81b4 + result = isDir ? 0x41fd : 0x81b4; + } + return (result & 0xFFFF) << 16; +}; + +/** + * Generate the DOS part of the external file attributes. + * @param {Object} dosPermissions the dos permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * Bit 0 Read-Only + * Bit 1 Hidden + * Bit 2 System + * Bit 3 Volume Label + * Bit 4 Directory + * Bit 5 Archive + */ +var generateDosExternalFileAttr = function (dosPermissions, isDir) { + + // the dir flag is already set for compatibility + return (dosPermissions || 0) & 0x3F; +}; + +/** + * Generate the various parts used in the construction of the final zip file. + * @param {Object} streamInfo the hash with informations about the compressed file. + * @param {Boolean} streamedContent is the content streamed ? + * @param {Boolean} streamingEnded is the stream finished ? + * @param {number} offset the current offset from the start of the zip file. + * @param {String} platform let's pretend we are this platform (change platform dependents fields) + * @param {Function} encodeFileName the function to encode the file name / comment. + * @return {Object} the zip parts. + */ +var generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) { + var file = streamInfo['file'], + compression = streamInfo['compression'], + useCustomEncoding = encodeFileName !== utf8.utf8encode, + encodedFileName = utils.transformTo("string", encodeFileName(file.name)), + utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), + comment = file.comment, + encodedComment = utils.transformTo("string", encodeFileName(comment)), + utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), + useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, + useUTF8ForComment = utfEncodedComment.length !== comment.length, + dosTime, + dosDate, + extraFields = "", + unicodePathExtraField = "", + unicodeCommentExtraField = "", + dir = file.dir, + date = file.date; + + + var dataInfo = { + crc32 : 0, + compressedSize : 0, + uncompressedSize : 0 + }; + + // if the content is streamed, the sizes/crc32 are only available AFTER + // the end of the stream. + if (!streamedContent || streamingEnded) { + dataInfo.crc32 = streamInfo['crc32']; + dataInfo.compressedSize = streamInfo['compressedSize']; + dataInfo.uncompressedSize = streamInfo['uncompressedSize']; + } + + var bitflag = 0; + if (streamedContent) { + // Bit 3: the sizes/crc32 are set to zero in the local header. + // The correct values are put in the data descriptor immediately + // following the compressed data. + bitflag |= 0x0008; + } + if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) { + // Bit 11: Language encoding flag (EFS). + bitflag |= 0x0800; + } + + + var extFileAttr = 0; + var versionMadeBy = 0; + if (dir) { + // dos or unix, we set the dos dir flag + extFileAttr |= 0x00010; + } + if(platform === "UNIX") { + versionMadeBy = 0x031E; // UNIX, version 3.0 + extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); + } else { // DOS or other, fallback to DOS + versionMadeBy = 0x0014; // DOS, version 2.0 + extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); + } + + // date + // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html + + dosTime = date.getUTCHours(); + dosTime = dosTime << 6; + dosTime = dosTime | date.getUTCMinutes(); + dosTime = dosTime << 5; + dosTime = dosTime | date.getUTCSeconds() / 2; + + dosDate = date.getUTCFullYear() - 1980; + dosDate = dosDate << 4; + dosDate = dosDate | (date.getUTCMonth() + 1); + dosDate = dosDate << 5; + dosDate = dosDate | date.getUTCDate(); + + if (useUTF8ForFileName) { + // set the unicode path extra field. unzip needs at least one extra + // field to correctly handle unicode path, so using the path is as good + // as any other information. This could improve the situation with + // other archive managers too. + // This field is usually used without the utf8 flag, with a non + // unicode path in the header (winrar, winzip). This helps (a bit) + // with the messy Windows' default compressed folders feature but + // breaks on p7zip which doesn't seek the unicode path extra field. + // So for now, UTF-8 everywhere ! + unicodePathExtraField = + // Version + decToHex(1, 1) + + // NameCRC32 + decToHex(crc32(encodedFileName), 4) + + // UnicodeName + utfEncodedFileName; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x70" + + // size + decToHex(unicodePathExtraField.length, 2) + + // content + unicodePathExtraField; + } + + if(useUTF8ForComment) { + + unicodeCommentExtraField = + // Version + decToHex(1, 1) + + // CommentCRC32 + decToHex(crc32(encodedComment), 4) + + // UnicodeName + utfEncodedComment; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x63" + + // size + decToHex(unicodeCommentExtraField.length, 2) + + // content + unicodeCommentExtraField; + } + + var header = ""; + + // version needed to extract + header += "\x0A\x00"; + // general purpose bit flag + header += decToHex(bitflag, 2); + // compression method + header += compression.magic; + // last mod file time + header += decToHex(dosTime, 2); + // last mod file date + header += decToHex(dosDate, 2); + // crc-32 + header += decToHex(dataInfo.crc32, 4); + // compressed size + header += decToHex(dataInfo.compressedSize, 4); + // uncompressed size + header += decToHex(dataInfo.uncompressedSize, 4); + // file name length + header += decToHex(encodedFileName.length, 2); + // extra field length + header += decToHex(extraFields.length, 2); + + + var fileRecord = signature.LOCAL_FILE_HEADER + header + encodedFileName + extraFields; + + var dirRecord = signature.CENTRAL_FILE_HEADER + + // version made by (00: DOS) + decToHex(versionMadeBy, 2) + + // file header (common to file and central directory) + header + + // file comment length + decToHex(encodedComment.length, 2) + + // disk number start + "\x00\x00" + + // internal file attributes TODO + "\x00\x00" + + // external file attributes + decToHex(extFileAttr, 4) + + // relative offset of local header + decToHex(offset, 4) + + // file name + encodedFileName + + // extra field + extraFields + + // file comment + encodedComment; + + return { + fileRecord: fileRecord, + dirRecord: dirRecord + }; +}; + +/** + * Generate the EOCD record. + * @param {Number} entriesCount the number of entries in the zip file. + * @param {Number} centralDirLength the length (in bytes) of the central dir. + * @param {Number} localDirLength the length (in bytes) of the local dir. + * @param {String} comment the zip file comment as a binary string. + * @param {Function} encodeFileName the function to encode the comment. + * @return {String} the EOCD record. + */ +var generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) { + var dirEnd = ""; + var encodedComment = utils.transformTo("string", encodeFileName(comment)); + + // end of central dir signature + dirEnd = signature.CENTRAL_DIRECTORY_END + + // number of this disk + "\x00\x00" + + // number of the disk with the start of the central directory + "\x00\x00" + + // total number of entries in the central directory on this disk + decToHex(entriesCount, 2) + + // total number of entries in the central directory + decToHex(entriesCount, 2) + + // size of the central directory 4 bytes + decToHex(centralDirLength, 4) + + // offset of start of central directory with respect to the starting disk number + decToHex(localDirLength, 4) + + // .ZIP file comment length + decToHex(encodedComment.length, 2) + + // .ZIP file comment + encodedComment; + + return dirEnd; +}; + +/** + * Generate data descriptors for a file entry. + * @param {Object} streamInfo the hash generated by a worker, containing informations + * on the file entry. + * @return {String} the data descriptors. + */ +var generateDataDescriptors = function (streamInfo) { + var descriptor = ""; + descriptor = signature.DATA_DESCRIPTOR + + // crc-32 4 bytes + decToHex(streamInfo['crc32'], 4) + + // compressed size 4 bytes + decToHex(streamInfo['compressedSize'], 4) + + // uncompressed size 4 bytes + decToHex(streamInfo['uncompressedSize'], 4); + + return descriptor; +}; + + +/** + * A worker to concatenate other workers to create a zip file. + * @param {Boolean} streamFiles `true` to stream the content of the files, + * `false` to accumulate it. + * @param {String} comment the comment to use. + * @param {String} platform the platform to use, "UNIX" or "DOS". + * @param {Function} encodeFileName the function to encode file names and comments. + */ +function ZipFileWorker(streamFiles, comment, platform, encodeFileName) { + GenericWorker.call(this, "ZipFileWorker"); + // The number of bytes written so far. This doesn't count accumulated chunks. + this.bytesWritten = 0; + // The comment of the zip file + this.zipComment = comment; + // The platform "generating" the zip file. + this.zipPlatform = platform; + // the function to encode file names and comments. + this.encodeFileName = encodeFileName; + // Should we stream the content of the files ? + this.streamFiles = streamFiles; + // If `streamFiles` is false, we will need to accumulate the content of the + // files to calculate sizes / crc32 (and write them *before* the content). + // This boolean indicates if we are accumulating chunks (it will change a lot + // during the lifetime of this worker). + this.accumulate = false; + // The buffer receiving chunks when accumulating content. + this.contentBuffer = []; + // The list of generated directory records. + this.dirRecords = []; + // The offset (in bytes) from the beginning of the zip file for the current source. + this.currentSourceOffset = 0; + // The total number of entries in this zip file. + this.entriesCount = 0; + // the name of the file currently being added, null when handling the end of the zip file. + // Used for the emited metadata. + this.currentFile = null; + + + + this._sources = []; +} +utils.inherits(ZipFileWorker, GenericWorker); + +/** + * @see GenericWorker.push + */ +ZipFileWorker.prototype.push = function (chunk) { + + var currentFilePercent = chunk.meta.percent || 0; + var entriesCount = this.entriesCount; + var remainingFiles = this._sources.length; + + if(this.accumulate) { + this.contentBuffer.push(chunk); + } else { + this.bytesWritten += chunk.data.length; + + GenericWorker.prototype.push.call(this, { + data : chunk.data, + meta : { + currentFile : this.currentFile, + percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100 + } + }); + } +}; + +/** + * The worker started a new source (an other worker). + * @param {Object} streamInfo the streamInfo object from the new source. + */ +ZipFileWorker.prototype.openedSource = function (streamInfo) { + this.currentSourceOffset = this.bytesWritten; + this.currentFile = streamInfo['file'].name; + + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + + // don't stream folders (because they don't have any content) + if(streamedContent) { + var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + } else { + // we need to wait for the whole file before pushing anything + this.accumulate = true; + } +}; + +/** + * The worker finished a source (an other worker). + * @param {Object} streamInfo the streamInfo object from the finished source. + */ +ZipFileWorker.prototype.closedSource = function (streamInfo) { + this.accumulate = false; + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + + this.dirRecords.push(record.dirRecord); + if(streamedContent) { + // after the streamed file, we put data descriptors + this.push({ + data : generateDataDescriptors(streamInfo), + meta : {percent:100} + }); + } else { + // the content wasn't streamed, we need to push everything now + // first the file record, then the content + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + while(this.contentBuffer.length) { + this.push(this.contentBuffer.shift()); + } + } + this.currentFile = null; +}; + +/** + * @see GenericWorker.flush + */ +ZipFileWorker.prototype.flush = function () { + + var localDirLength = this.bytesWritten; + for(var i = 0; i < this.dirRecords.length; i++) { + this.push({ + data : this.dirRecords[i], + meta : {percent:100} + }); + } + var centralDirLength = this.bytesWritten - localDirLength; + + var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName); + + this.push({ + data : dirEnd, + meta : {percent:100} + }); +}; + +/** + * Prepare the next source to be read. + */ +ZipFileWorker.prototype.prepareNextSource = function () { + this.previous = this._sources.shift(); + this.openedSource(this.previous.streamInfo); + if (this.isPaused) { + this.previous.pause(); + } else { + this.previous.resume(); + } +}; + +/** + * @see GenericWorker.registerPrevious + */ +ZipFileWorker.prototype.registerPrevious = function (previous) { + this._sources.push(previous); + var self = this; + + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.closedSource(self.previous.streamInfo); + if(self._sources.length) { + self.prepareNextSource(); + } else { + self.end(); + } + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; +}; + +/** + * @see GenericWorker.resume + */ +ZipFileWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this.previous && this._sources.length) { + this.prepareNextSource(); + return true; + } + if (!this.previous && !this._sources.length && !this.generatedError) { + this.end(); + return true; + } +}; + +/** + * @see GenericWorker.error + */ +ZipFileWorker.prototype.error = function (e) { + var sources = this._sources; + if(!GenericWorker.prototype.error.call(this, e)) { + return false; + } + for(var i = 0; i < sources.length; i++) { + try { + sources[i].error(e); + } catch(e) { + // the `error` exploded, nothing to do + } + } + return true; +}; + +/** + * @see GenericWorker.lock + */ +ZipFileWorker.prototype.lock = function () { + GenericWorker.prototype.lock.call(this); + var sources = this._sources; + for(var i = 0; i < sources.length; i++) { + sources[i].lock(); + } +}; + +module.exports = ZipFileWorker; + +},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(require,module,exports){ +'use strict'; + +var compressions = require('../compressions'); +var ZipFileWorker = require('./ZipFileWorker'); + +/** + * Find the compression to use. + * @param {String} fileCompression the compression defined at the file level, if any. + * @param {String} zipCompression the compression defined at the load() level. + * @return {Object} the compression object to use. + */ +var getCompression = function (fileCompression, zipCompression) { + + var compressionName = fileCompression || zipCompression; + var compression = compressions[compressionName]; + if (!compression) { + throw new Error(compressionName + " is not a valid compression method !"); + } + return compression; +}; + +/** + * Create a worker to generate a zip file. + * @param {JSZip} zip the JSZip instance at the right root level. + * @param {Object} options to generate the zip file. + * @param {String} comment the comment to use. + */ +exports.generateWorker = function (zip, options, comment) { + + var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName); + var entriesCount = 0; + try { + + zip.forEach(function (relativePath, file) { + entriesCount++; + var compression = getCompression(file.options.compression, options.compression); + var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; + var dir = file.dir, date = file.date; + + file._compressWorker(compression, compressionOptions) + .withStreamInfo("file", { + name : relativePath, + dir : dir, + date : date, + comment : file.comment || "", + unixPermissions : file.unixPermissions, + dosPermissions : file.dosPermissions + }) + .pipe(zipFileWorker); + }); + zipFileWorker.entriesCount = entriesCount; + } catch (e) { + zipFileWorker.error(e); + } + + return zipFileWorker; +}; + +},{"../compressions":3,"./ZipFileWorker":8}],10:[function(require,module,exports){ +'use strict'; + +/** + * Representation a of zip file in js + * @constructor + */ +function JSZip() { + // if this constructor is used without `new`, it adds `new` before itself: + if(!(this instanceof JSZip)) { + return new JSZip(); + } + + if(arguments.length) { + throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); + } + + // object containing the files : + // { + // "folder/" : {...}, + // "folder/data.txt" : {...} + // } + this.files = {}; + + this.comment = null; + + // Where we are in the hierarchy + this.root = ""; + this.clone = function() { + var newObj = new JSZip(); + for (var i in this) { + if (typeof this[i] !== "function") { + newObj[i] = this[i]; + } + } + return newObj; + }; +} +JSZip.prototype = require('./object'); +JSZip.prototype.loadAsync = require('./load'); +JSZip.support = require('./support'); +JSZip.defaults = require('./defaults'); + +// TODO find a better way to handle this version, +// a require('package.json').version doesn't work with webpack, see #327 +JSZip.version = "3.1.5"; + +JSZip.loadAsync = function (content, options) { + return new JSZip().loadAsync(content, options); +}; + +JSZip.external = require("./external"); +module.exports = JSZip; + +},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(require,module,exports){ +'use strict'; +var utils = require('./utils'); +var external = require("./external"); +var utf8 = require('./utf8'); +var utils = require('./utils'); +var ZipEntries = require('./zipEntries'); +var Crc32Probe = require('./stream/Crc32Probe'); +var nodejsUtils = require("./nodejsUtils"); + +/** + * Check the CRC32 of an entry. + * @param {ZipEntry} zipEntry the zip entry to check. + * @return {Promise} the result. + */ +function checkEntryCRC32(zipEntry) { + return new external.Promise(function (resolve, reject) { + var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe()); + worker.on("error", function (e) { + reject(e); + }) + .on("end", function () { + if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) { + reject(new Error("Corrupted zip : CRC32 mismatch")); + } else { + resolve(); + } + }) + .resume(); + }); +} + +module.exports = function(data, options) { + var zip = this; + options = utils.extend(options || {}, { + base64: false, + checkCRC32: false, + optimizedBinaryString: false, + createFolders: false, + decodeFileName: utf8.utf8decode + }); + + if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + return external.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")); + } + + return utils.prepareContent("the loaded zip file", data, true, options.optimizedBinaryString, options.base64) + .then(function(data) { + var zipEntries = new ZipEntries(options); + zipEntries.load(data); + return zipEntries; + }).then(function checkCRC32(zipEntries) { + var promises = [external.Promise.resolve(zipEntries)]; + var files = zipEntries.files; + if (options.checkCRC32) { + for (var i = 0; i < files.length; i++) { + promises.push(checkEntryCRC32(files[i])); + } + } + return external.Promise.all(promises); + }).then(function addFiles(results) { + var zipEntries = results.shift(); + var files = zipEntries.files; + for (var i = 0; i < files.length; i++) { + var input = files[i]; + zip.file(input.fileNameStr, input.decompressed, { + binary: true, + optimizedBinaryString: true, + date: input.date, + dir: input.dir, + comment : input.fileCommentStr.length ? input.fileCommentStr : null, + unixPermissions : input.unixPermissions, + dosPermissions : input.dosPermissions, + createFolders: options.createFolders + }); + } + if (zipEntries.zipComment.length) { + zip.comment = zipEntries.zipComment; + } + + return zip; + }); +}; + +},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(require,module,exports){ +"use strict"; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); + +/** + * A worker that use a nodejs stream as source. + * @constructor + * @param {String} filename the name of the file entry for this stream. + * @param {Readable} stream the nodejs stream. + */ +function NodejsStreamInputAdapter(filename, stream) { + GenericWorker.call(this, "Nodejs stream input adapter for " + filename); + this._upstreamEnded = false; + this._bindStream(stream); +} + +utils.inherits(NodejsStreamInputAdapter, GenericWorker); + +/** + * Prepare the stream and bind the callbacks on it. + * Do this ASAP on node 0.10 ! A lazy binding doesn't always work. + * @param {Stream} stream the nodejs stream to use. + */ +NodejsStreamInputAdapter.prototype._bindStream = function (stream) { + var self = this; + this._stream = stream; + stream.pause(); + stream + .on("data", function (chunk) { + self.push({ + data: chunk, + meta : { + percent : 0 + } + }); + }) + .on("error", function (e) { + if(self.isPaused) { + this.generatedError = e; + } else { + self.error(e); + } + }) + .on("end", function () { + if(self.isPaused) { + self._upstreamEnded = true; + } else { + self.end(); + } + }); +}; +NodejsStreamInputAdapter.prototype.pause = function () { + if(!GenericWorker.prototype.pause.call(this)) { + return false; + } + this._stream.pause(); + return true; +}; +NodejsStreamInputAdapter.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if(this._upstreamEnded) { + this.end(); + } else { + this._stream.resume(); + } + + return true; +}; + +module.exports = NodejsStreamInputAdapter; + +},{"../stream/GenericWorker":28,"../utils":32}],13:[function(require,module,exports){ +'use strict'; + +var Readable = require('readable-stream').Readable; + +var utils = require('../utils'); +utils.inherits(NodejsStreamOutputAdapter, Readable); + +/** +* A nodejs stream using a worker as source. +* @see the SourceWrapper in http://nodejs.org/api/stream.html +* @constructor +* @param {StreamHelper} helper the helper wrapping the worker +* @param {Object} options the nodejs stream options +* @param {Function} updateCb the update callback. +*/ +function NodejsStreamOutputAdapter(helper, options, updateCb) { + Readable.call(this, options); + this._helper = helper; + + var self = this; + helper.on("data", function (data, meta) { + if (!self.push(data)) { + self._helper.pause(); + } + if(updateCb) { + updateCb(meta); + } + }) + .on("error", function(e) { + self.emit('error', e); + }) + .on("end", function () { + self.push(null); + }); +} + + +NodejsStreamOutputAdapter.prototype._read = function() { + this._helper.resume(); +}; + +module.exports = NodejsStreamOutputAdapter; + +},{"../utils":32,"readable-stream":16}],14:[function(require,module,exports){ +'use strict'; + +module.exports = { + /** + * True if this is running in Nodejs, will be undefined in a browser. + * In a browser, browserify won't include this file and the whole module + * will be resolved an empty object. + */ + isNode : typeof Buffer !== "undefined", + /** + * Create a new nodejs Buffer from an existing content. + * @param {Object} data the data to pass to the constructor. + * @param {String} encoding the encoding to use. + * @return {Buffer} a new Buffer. + */ + newBufferFrom: function(data, encoding) { + // XXX We can't use `Buffer.from` which comes from `Uint8Array.from` + // in nodejs v4 (< v.4.5). It's not the expected implementation (and + // has a different signature). + // see https://github.com/nodejs/node/issues/8053 + // A condition on nodejs' version won't solve the issue as we don't + // control the Buffer polyfills that may or may not be used. + return new Buffer(data, encoding); + }, + /** + * Create a new nodejs Buffer with the specified size. + * @param {Integer} size the size of the buffer. + * @return {Buffer} a new Buffer. + */ + allocBuffer: function (size) { + if (Buffer.alloc) { + return Buffer.alloc(size); + } else { + return new Buffer(size); + } + }, + /** + * Find out if an object is a Buffer. + * @param {Object} b the object to test. + * @return {Boolean} true if the object is a Buffer, false otherwise. + */ + isBuffer : function(b){ + return Buffer.isBuffer(b); + }, + + isStream : function (obj) { + return obj && + typeof obj.on === "function" && + typeof obj.pause === "function" && + typeof obj.resume === "function"; + } +}; + +},{}],15:[function(require,module,exports){ +'use strict'; +var utf8 = require('./utf8'); +var utils = require('./utils'); +var GenericWorker = require('./stream/GenericWorker'); +var StreamHelper = require('./stream/StreamHelper'); +var defaults = require('./defaults'); +var CompressedObject = require('./compressedObject'); +var ZipObject = require('./zipObject'); +var generate = require("./generate"); +var nodejsUtils = require("./nodejsUtils"); +var NodejsStreamInputAdapter = require("./nodejs/NodejsStreamInputAdapter"); + + +/** + * Add a file in the current folder. + * @private + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file + * @param {Object} originalOptions the options of the file + * @return {Object} the new file. + */ +var fileAdd = function(name, data, originalOptions) { + // be sure sub folders exist + var dataType = utils.getTypeOf(data), + parent; + + + /* + * Correct options. + */ + + var o = utils.extend(originalOptions || {}, defaults); + o.date = o.date || new Date(); + if (o.compression !== null) { + o.compression = o.compression.toUpperCase(); + } + + if (typeof o.unixPermissions === "string") { + o.unixPermissions = parseInt(o.unixPermissions, 8); + } + + // UNX_IFDIR 0040000 see zipinfo.c + if (o.unixPermissions && (o.unixPermissions & 0x4000)) { + o.dir = true; + } + // Bit 4 Directory + if (o.dosPermissions && (o.dosPermissions & 0x0010)) { + o.dir = true; + } + + if (o.dir) { + name = forceTrailingSlash(name); + } + if (o.createFolders && (parent = parentFolder(name))) { + folderAdd.call(this, parent, true); + } + + var isUnicodeString = dataType === "string" && o.binary === false && o.base64 === false; + if (!originalOptions || typeof originalOptions.binary === "undefined") { + o.binary = !isUnicodeString; + } + + + var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0; + + if (isCompressedEmpty || o.dir || !data || data.length === 0) { + o.base64 = false; + o.binary = true; + data = ""; + o.compression = "STORE"; + dataType = "string"; + } + + /* + * Convert content to fit. + */ + + var zipObjectContent = null; + if (data instanceof CompressedObject || data instanceof GenericWorker) { + zipObjectContent = data; + } else if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + zipObjectContent = new NodejsStreamInputAdapter(name, data); + } else { + zipObjectContent = utils.prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64); + } + + var object = new ZipObject(name, zipObjectContent, o); + this.files[name] = object; + /* + TODO: we can't throw an exception because we have async promises + (we can have a promise of a Date() for example) but returning a + promise is useless because file(name, data) returns the JSZip + object for chaining. Should we break that to allow the user + to catch the error ? + + return external.Promise.resolve(zipObjectContent) + .then(function () { + return object; + }); + */ +}; + +/** + * Find the parent folder of the path. + * @private + * @param {string} path the path to use + * @return {string} the parent folder, or "" + */ +var parentFolder = function (path) { + if (path.slice(-1) === '/') { + path = path.substring(0, path.length - 1); + } + var lastSlash = path.lastIndexOf('/'); + return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; +}; + +/** + * Returns the path with a slash at the end. + * @private + * @param {String} path the path to check. + * @return {String} the path with a trailing slash. + */ +var forceTrailingSlash = function(path) { + // Check the name ends with a / + if (path.slice(-1) !== "/") { + path += "/"; // IE doesn't like substr(-1) + } + return path; +}; + +/** + * Add a (sub) folder in the current folder. + * @private + * @param {string} name the folder's name + * @param {boolean=} [createFolders] If true, automatically create sub + * folders. Defaults to false. + * @return {Object} the new folder. + */ +var folderAdd = function(name, createFolders) { + createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders; + + name = forceTrailingSlash(name); + + // Does this folder already exist? + if (!this.files[name]) { + fileAdd.call(this, name, null, { + dir: true, + createFolders: createFolders + }); + } + return this.files[name]; +}; + +/** +* Cross-window, cross-Node-context regular expression detection +* @param {Object} object Anything +* @return {Boolean} true if the object is a regular expression, +* false otherwise +*/ +function isRegExp(object) { + return Object.prototype.toString.call(object) === "[object RegExp]"; +} + +// return the actual prototype of JSZip +var out = { + /** + * @see loadAsync + */ + load: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + + /** + * Call a callback function for each entry at this folder level. + * @param {Function} cb the callback function: + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + */ + forEach: function(cb) { + var filename, relativePath, file; + for (filename in this.files) { + if (!this.files.hasOwnProperty(filename)) { + continue; + } + file = this.files[filename]; + relativePath = filename.slice(this.root.length, filename.length); + if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root + cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn... + } + } + }, + + /** + * Filter nested files/folders with the specified function. + * @param {Function} search the predicate to use : + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + * @return {Array} An array of matching elements. + */ + filter: function(search) { + var result = []; + this.forEach(function (relativePath, entry) { + if (search(relativePath, entry)) { // the file matches the function + result.push(entry); + } + + }); + return result; + }, + + /** + * Add a file to the zip file, or search a file. + * @param {string|RegExp} name The name of the file to add (if data is defined), + * the name of the file to find (if no data) or a regex to match files. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded + * @param {Object} o File options + * @return {JSZip|Object|Array} this JSZip object (when adding a file), + * a file (when searching by string) or an array of files (when searching by regex). + */ + file: function(name, data, o) { + if (arguments.length === 1) { + if (isRegExp(name)) { + var regexp = name; + return this.filter(function(relativePath, file) { + return !file.dir && regexp.test(relativePath); + }); + } + else { // text + var obj = this.files[this.root + name]; + if (obj && !obj.dir) { + return obj; + } else { + return null; + } + } + } + else { // more than one argument : we have data ! + name = this.root + name; + fileAdd.call(this, name, data, o); + } + return this; + }, + + /** + * Add a directory to the zip file, or search. + * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. + * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. + */ + folder: function(arg) { + if (!arg) { + return this; + } + + if (isRegExp(arg)) { + return this.filter(function(relativePath, file) { + return file.dir && arg.test(relativePath); + }); + } + + // else, name is a new folder + var name = this.root + arg; + var newFolder = folderAdd.call(this, name); + + // Allow chaining by returning a new object with this folder as the root + var ret = this.clone(); + ret.root = newFolder.name; + return ret; + }, + + /** + * Delete a file, or a directory and all sub-files, from the zip + * @param {string} name the name of the file to delete + * @return {JSZip} this JSZip object + */ + remove: function(name) { + name = this.root + name; + var file = this.files[name]; + if (!file) { + // Look for any folders + if (name.slice(-1) !== "/") { + name += "/"; + } + file = this.files[name]; + } + + if (file && !file.dir) { + // file + delete this.files[name]; + } else { + // maybe a folder, delete recursively + var kids = this.filter(function(relativePath, file) { + return file.name.slice(0, name.length) === name; + }); + for (var i = 0; i < kids.length; i++) { + delete this.files[kids[i].name]; + } + } + + return this; + }, + + /** + * Generate the complete zip file + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file + */ + generate: function(options) { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + /** + * Generate the complete zip file as an internal stream. + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {StreamHelper} the streamed zip file. + */ + generateInternalStream: function(options) { + var worker, opts = {}; + try { + opts = utils.extend(options || {}, { + streamFiles: false, + compression: "STORE", + compressionOptions : null, + type: "", + platform: "DOS", + comment: null, + mimeType: 'application/zip', + encodeFileName: utf8.utf8encode + }); + + opts.type = opts.type.toLowerCase(); + opts.compression = opts.compression.toUpperCase(); + + // "binarystring" is prefered but the internals use "string". + if(opts.type === "binarystring") { + opts.type = "string"; + } + + if (!opts.type) { + throw new Error("No output type specified."); + } + + utils.checkSupport(opts.type); + + // accept nodejs `process.platform` + if( + opts.platform === 'darwin' || + opts.platform === 'freebsd' || + opts.platform === 'linux' || + opts.platform === 'sunos' + ) { + opts.platform = "UNIX"; + } + if (opts.platform === 'win32') { + opts.platform = "DOS"; + } + + var comment = opts.comment || this.comment || ""; + worker = generate.generateWorker(this, opts, comment); + } catch (e) { + worker = new GenericWorker("error"); + worker.error(e); + } + return new StreamHelper(worker, opts.type || "string", opts.mimeType); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateAsync: function(options, onUpdate) { + return this.generateInternalStream(options).accumulate(onUpdate); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateNodeStream: function(options, onUpdate) { + options = options || {}; + if (!options.type) { + options.type = "nodebuffer"; + } + return this.generateInternalStream(options).toNodejsStream(onUpdate); + } +}; +module.exports = out; + +},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(require,module,exports){ +/* + * This file is used by module bundlers (browserify/webpack/etc) when + * including a stream implementation. We use "readable-stream" to get a + * consistent behavior between nodejs versions but bundlers often have a shim + * for "stream". Using this shim greatly improve the compatibility and greatly + * reduce the final size of the bundle (only one stream implementation, not + * two). + */ +module.exports = require("stream"); + +},{"stream":undefined}],17:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function ArrayReader(data) { + DataReader.call(this, data); + for(var i = 0; i < this.data.length; i++) { + data[i] = data[i] & 0xFF; + } +} +utils.inherits(ArrayReader, DataReader); +/** + * @see DataReader.byteAt + */ +ArrayReader.prototype.byteAt = function(i) { + return this.data[this.zero + i]; +}; +/** + * @see DataReader.lastIndexOfSignature + */ +ArrayReader.prototype.lastIndexOfSignature = function(sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3); + for (var i = this.length - 4; i >= 0; --i) { + if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { + return i - this.zero; + } + } + + return -1; +}; +/** + * @see DataReader.readAndCheckSignature + */ +ArrayReader.prototype.readAndCheckSignature = function (sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3), + data = this.readData(4); + return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3]; +}; +/** + * @see DataReader.readData + */ +ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + return []; + } + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = ArrayReader; + +},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){ +'use strict'; +var utils = require('../utils'); + +function DataReader(data) { + this.data = data; // type : see implementation + this.length = data.length; + this.index = 0; + this.zero = 0; +} +DataReader.prototype = { + /** + * Check that the offset will not go too far. + * @param {string} offset the additional offset to check. + * @throws {Error} an Error if the offset is out of bounds. + */ + checkOffset: function(offset) { + this.checkIndex(this.index + offset); + }, + /** + * Check that the specified index will not be too far. + * @param {string} newIndex the index to check. + * @throws {Error} an Error if the index is out of bounds. + */ + checkIndex: function(newIndex) { + if (this.length < this.zero + newIndex || newIndex < 0) { + throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); + } + }, + /** + * Change the index. + * @param {number} newIndex The new index. + * @throws {Error} if the new index is out of the data. + */ + setIndex: function(newIndex) { + this.checkIndex(newIndex); + this.index = newIndex; + }, + /** + * Skip the next n bytes. + * @param {number} n the number of bytes to skip. + * @throws {Error} if the new index is out of the data. + */ + skip: function(n) { + this.setIndex(this.index + n); + }, + /** + * Get the byte at the specified index. + * @param {number} i the index to use. + * @return {number} a byte. + */ + byteAt: function(i) { + // see implementations + }, + /** + * Get the next number with a given byte size. + * @param {number} size the number of bytes to read. + * @return {number} the corresponding number. + */ + readInt: function(size) { + var result = 0, + i; + this.checkOffset(size); + for (i = this.index + size - 1; i >= this.index; i--) { + result = (result << 8) + this.byteAt(i); + } + this.index += size; + return result; + }, + /** + * Get the next string with a given byte size. + * @param {number} size the number of bytes to read. + * @return {string} the corresponding string. + */ + readString: function(size) { + return utils.transformTo("string", this.readData(size)); + }, + /** + * Get raw data without conversion, bytes. + * @param {number} size the number of bytes to read. + * @return {Object} the raw data, implementation specific. + */ + readData: function(size) { + // see implementations + }, + /** + * Find the last occurence of a zip signature (4 bytes). + * @param {string} sig the signature to find. + * @return {number} the index of the last occurence, -1 if not found. + */ + lastIndexOfSignature: function(sig) { + // see implementations + }, + /** + * Read the signature (4 bytes) at the current position and compare it with sig. + * @param {string} sig the expected signature + * @return {boolean} true if the signature matches, false otherwise. + */ + readAndCheckSignature: function(sig) { + // see implementations + }, + /** + * Get the next date. + * @return {Date} the date. + */ + readDate: function() { + var dostime = this.readInt(4); + return new Date(Date.UTC( + ((dostime >> 25) & 0x7f) + 1980, // year + ((dostime >> 21) & 0x0f) - 1, // month + (dostime >> 16) & 0x1f, // day + (dostime >> 11) & 0x1f, // hour + (dostime >> 5) & 0x3f, // minute + (dostime & 0x1f) << 1)); // second + } +}; +module.exports = DataReader; + +},{"../utils":32}],19:[function(require,module,exports){ +'use strict'; +var Uint8ArrayReader = require('./Uint8ArrayReader'); +var utils = require('../utils'); + +function NodeBufferReader(data) { + Uint8ArrayReader.call(this, data); +} +utils.inherits(NodeBufferReader, Uint8ArrayReader); + +/** + * @see DataReader.readData + */ +NodeBufferReader.prototype.readData = function(size) { + this.checkOffset(size); + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = NodeBufferReader; + +},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function StringReader(data) { + DataReader.call(this, data); +} +utils.inherits(StringReader, DataReader); +/** + * @see DataReader.byteAt + */ +StringReader.prototype.byteAt = function(i) { + return this.data.charCodeAt(this.zero + i); +}; +/** + * @see DataReader.lastIndexOfSignature + */ +StringReader.prototype.lastIndexOfSignature = function(sig) { + return this.data.lastIndexOf(sig) - this.zero; +}; +/** + * @see DataReader.readAndCheckSignature + */ +StringReader.prototype.readAndCheckSignature = function (sig) { + var data = this.readData(4); + return sig === data; +}; +/** + * @see DataReader.readData + */ +StringReader.prototype.readData = function(size) { + this.checkOffset(size); + // this will work because the constructor applied the "& 0xff" mask. + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = StringReader; + +},{"../utils":32,"./DataReader":18}],21:[function(require,module,exports){ +'use strict'; +var ArrayReader = require('./ArrayReader'); +var utils = require('../utils'); + +function Uint8ArrayReader(data) { + ArrayReader.call(this, data); +} +utils.inherits(Uint8ArrayReader, ArrayReader); +/** + * @see DataReader.readData + */ +Uint8ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. + return new Uint8Array(0); + } + var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = Uint8ArrayReader; + +},{"../utils":32,"./ArrayReader":17}],22:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var support = require('../support'); +var ArrayReader = require('./ArrayReader'); +var StringReader = require('./StringReader'); +var NodeBufferReader = require('./NodeBufferReader'); +var Uint8ArrayReader = require('./Uint8ArrayReader'); + +/** + * Create a reader adapted to the data. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read. + * @return {DataReader} the data reader. + */ +module.exports = function (data) { + var type = utils.getTypeOf(data); + utils.checkSupport(type); + if (type === "string" && !support.uint8array) { + return new StringReader(data); + } + if (type === "nodebuffer") { + return new NodeBufferReader(data); + } + if (support.uint8array) { + return new Uint8ArrayReader(utils.transformTo("uint8array", data)); + } + return new ArrayReader(utils.transformTo("array", data)); +}; + +},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(require,module,exports){ +'use strict'; +exports.LOCAL_FILE_HEADER = "PK\x03\x04"; +exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; +exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; +exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; +exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; +exports.DATA_DESCRIPTOR = "PK\x07\x08"; + +},{}],24:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var utils = require('../utils'); + +/** + * A worker which convert chunks to a specified type. + * @constructor + * @param {String} destType the destination type. + */ +function ConvertWorker(destType) { + GenericWorker.call(this, "ConvertWorker to " + destType); + this.destType = destType; +} +utils.inherits(ConvertWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +ConvertWorker.prototype.processChunk = function (chunk) { + this.push({ + data : utils.transformTo(this.destType, chunk.data), + meta : chunk.meta + }); +}; +module.exports = ConvertWorker; + +},{"../utils":32,"./GenericWorker":28}],25:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var crc32 = require('../crc32'); +var utils = require('../utils'); + +/** + * A worker which calculate the crc32 of the data flowing through. + * @constructor + */ +function Crc32Probe() { + GenericWorker.call(this, "Crc32Probe"); + this.withStreamInfo("crc32", 0); +} +utils.inherits(Crc32Probe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Crc32Probe.prototype.processChunk = function (chunk) { + this.streamInfo.crc32 = crc32(chunk.data, this.streamInfo.crc32 || 0); + this.push(chunk); +}; +module.exports = Crc32Probe; + +},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +/** + * A worker which calculate the total length of the data flowing through. + * @constructor + * @param {String} propName the name used to expose the length + */ +function DataLengthProbe(propName) { + GenericWorker.call(this, "DataLengthProbe for " + propName); + this.propName = propName; + this.withStreamInfo(propName, 0); +} +utils.inherits(DataLengthProbe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +DataLengthProbe.prototype.processChunk = function (chunk) { + if(chunk) { + var length = this.streamInfo[this.propName] || 0; + this.streamInfo[this.propName] = length + chunk.data.length; + } + GenericWorker.prototype.processChunk.call(this, chunk); +}; +module.exports = DataLengthProbe; + + +},{"../utils":32,"./GenericWorker":28}],27:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +// the size of the generated chunks +// TODO expose this as a public variable +var DEFAULT_BLOCK_SIZE = 16 * 1024; + +/** + * A worker that reads a content and emits chunks. + * @constructor + * @param {Promise} dataP the promise of the data to split + */ +function DataWorker(dataP) { + GenericWorker.call(this, "DataWorker"); + var self = this; + this.dataIsReady = false; + this.index = 0; + this.max = 0; + this.data = null; + this.type = ""; + + this._tickScheduled = false; + + dataP.then(function (data) { + self.dataIsReady = true; + self.data = data; + self.max = data && data.length || 0; + self.type = utils.getTypeOf(data); + if(!self.isPaused) { + self._tickAndRepeat(); + } + }, function (e) { + self.error(e); + }); +} + +utils.inherits(DataWorker, GenericWorker); + +/** + * @see GenericWorker.cleanUp + */ +DataWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this.data = null; +}; + +/** + * @see GenericWorker.resume + */ +DataWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this._tickScheduled && this.dataIsReady) { + this._tickScheduled = true; + utils.delay(this._tickAndRepeat, [], this); + } + return true; +}; + +/** + * Trigger a tick a schedule an other call to this function. + */ +DataWorker.prototype._tickAndRepeat = function() { + this._tickScheduled = false; + if(this.isPaused || this.isFinished) { + return; + } + this._tick(); + if(!this.isFinished) { + utils.delay(this._tickAndRepeat, [], this); + this._tickScheduled = true; + } +}; + +/** + * Read and push a chunk. + */ +DataWorker.prototype._tick = function() { + + if(this.isPaused || this.isFinished) { + return false; + } + + var size = DEFAULT_BLOCK_SIZE; + var data = null, nextIndex = Math.min(this.max, this.index + size); + if (this.index >= this.max) { + // EOF + return this.end(); + } else { + switch(this.type) { + case "string": + data = this.data.substring(this.index, nextIndex); + break; + case "uint8array": + data = this.data.subarray(this.index, nextIndex); + break; + case "array": + case "nodebuffer": + data = this.data.slice(this.index, nextIndex); + break; + } + this.index = nextIndex; + return this.push({ + data : data, + meta : { + percent : this.max ? this.index / this.max * 100 : 0 + } + }); + } +}; + +module.exports = DataWorker; + +},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){ +'use strict'; + +/** + * A worker that does nothing but passing chunks to the next one. This is like + * a nodejs stream but with some differences. On the good side : + * - it works on IE 6-9 without any issue / polyfill + * - it weights less than the full dependencies bundled with browserify + * - it forwards errors (no need to declare an error handler EVERYWHERE) + * + * A chunk is an object with 2 attributes : `meta` and `data`. The former is an + * object containing anything (`percent` for example), see each worker for more + * details. The latter is the real data (String, Uint8Array, etc). + * + * @constructor + * @param {String} name the name of the stream (mainly used for debugging purposes) + */ +function GenericWorker(name) { + // the name of the worker + this.name = name || "default"; + // an object containing metadata about the workers chain + this.streamInfo = {}; + // an error which happened when the worker was paused + this.generatedError = null; + // an object containing metadata to be merged by this worker into the general metadata + this.extraStreamInfo = {}; + // true if the stream is paused (and should not do anything), false otherwise + this.isPaused = true; + // true if the stream is finished (and should not do anything), false otherwise + this.isFinished = false; + // true if the stream is locked to prevent further structure updates (pipe), false otherwise + this.isLocked = false; + // the event listeners + this._listeners = { + 'data':[], + 'end':[], + 'error':[] + }; + // the previous worker, if any + this.previous = null; +} + +GenericWorker.prototype = { + /** + * Push a chunk to the next workers. + * @param {Object} chunk the chunk to push + */ + push : function (chunk) { + this.emit("data", chunk); + }, + /** + * End the stream. + * @return {Boolean} true if this call ended the worker, false otherwise. + */ + end : function () { + if (this.isFinished) { + return false; + } + + this.flush(); + try { + this.emit("end"); + this.cleanUp(); + this.isFinished = true; + } catch (e) { + this.emit("error", e); + } + return true; + }, + /** + * End the stream with an error. + * @param {Error} e the error which caused the premature end. + * @return {Boolean} true if this call ended the worker with an error, false otherwise. + */ + error : function (e) { + if (this.isFinished) { + return false; + } + + if(this.isPaused) { + this.generatedError = e; + } else { + this.isFinished = true; + + this.emit("error", e); + + // in the workers chain exploded in the middle of the chain, + // the error event will go downward but we also need to notify + // workers upward that there has been an error. + if(this.previous) { + this.previous.error(e); + } + + this.cleanUp(); + } + return true; + }, + /** + * Add a callback on an event. + * @param {String} name the name of the event (data, end, error) + * @param {Function} listener the function to call when the event is triggered + * @return {GenericWorker} the current object for chainability + */ + on : function (name, listener) { + this._listeners[name].push(listener); + return this; + }, + /** + * Clean any references when a worker is ending. + */ + cleanUp : function () { + this.streamInfo = this.generatedError = this.extraStreamInfo = null; + this._listeners = []; + }, + /** + * Trigger an event. This will call registered callback with the provided arg. + * @param {String} name the name of the event (data, end, error) + * @param {Object} arg the argument to call the callback with. + */ + emit : function (name, arg) { + if (this._listeners[name]) { + for(var i = 0; i < this._listeners[name].length; i++) { + this._listeners[name][i].call(this, arg); + } + } + }, + /** + * Chain a worker with an other. + * @param {Worker} next the worker receiving events from the current one. + * @return {worker} the next worker for chainability + */ + pipe : function (next) { + return next.registerPrevious(this); + }, + /** + * Same as `pipe` in the other direction. + * Using an API with `pipe(next)` is very easy. + * Implementing the API with the point of view of the next one registering + * a source is easier, see the ZipFileWorker. + * @param {Worker} previous the previous worker, sending events to this one + * @return {Worker} the current worker for chainability + */ + registerPrevious : function (previous) { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + + // sharing the streamInfo... + this.streamInfo = previous.streamInfo; + // ... and adding our own bits + this.mergeStreamInfo(); + this.previous = previous; + var self = this; + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.end(); + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; + }, + /** + * Pause the stream so it doesn't send events anymore. + * @return {Boolean} true if this call paused the worker, false otherwise. + */ + pause : function () { + if(this.isPaused || this.isFinished) { + return false; + } + this.isPaused = true; + + if(this.previous) { + this.previous.pause(); + } + return true; + }, + /** + * Resume a paused stream. + * @return {Boolean} true if this call resumed the worker, false otherwise. + */ + resume : function () { + if(!this.isPaused || this.isFinished) { + return false; + } + this.isPaused = false; + + // if true, the worker tried to resume but failed + var withError = false; + if(this.generatedError) { + this.error(this.generatedError); + withError = true; + } + if(this.previous) { + this.previous.resume(); + } + + return !withError; + }, + /** + * Flush any remaining bytes as the stream is ending. + */ + flush : function () {}, + /** + * Process a chunk. This is usually the method overridden. + * @param {Object} chunk the chunk to process. + */ + processChunk : function(chunk) { + this.push(chunk); + }, + /** + * Add a key/value to be added in the workers chain streamInfo once activated. + * @param {String} key the key to use + * @param {Object} value the associated value + * @return {Worker} the current worker for chainability + */ + withStreamInfo : function (key, value) { + this.extraStreamInfo[key] = value; + this.mergeStreamInfo(); + return this; + }, + /** + * Merge this worker's streamInfo into the chain's streamInfo. + */ + mergeStreamInfo : function () { + for(var key in this.extraStreamInfo) { + if (!this.extraStreamInfo.hasOwnProperty(key)) { + continue; + } + this.streamInfo[key] = this.extraStreamInfo[key]; + } + }, + + /** + * Lock the stream to prevent further updates on the workers chain. + * After calling this method, all calls to pipe will fail. + */ + lock: function () { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + this.isLocked = true; + if (this.previous) { + this.previous.lock(); + } + }, + + /** + * + * Pretty print the workers chain. + */ + toString : function () { + var me = "Worker " + this.name; + if (this.previous) { + return this.previous + " -> " + me; + } else { + return me; + } + } +}; + +module.exports = GenericWorker; + +},{}],29:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var ConvertWorker = require('./ConvertWorker'); +var GenericWorker = require('./GenericWorker'); +var base64 = require('../base64'); +var support = require("../support"); +var external = require("../external"); + +var NodejsStreamOutputAdapter = null; +if (support.nodestream) { + try { + NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter'); + } catch(e) {} +} + +/** + * Apply the final transformation of the data. If the user wants a Blob for + * example, it's easier to work with an U8intArray and finally do the + * ArrayBuffer/Blob conversion. + * @param {String} type the name of the final type + * @param {String|Uint8Array|Buffer} content the content to transform + * @param {String} mimeType the mime type of the content, if applicable. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. + */ +function transformZipOutput(type, content, mimeType) { + switch(type) { + case "blob" : + return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); + case "base64" : + return base64.encode(content); + default : + return utils.transformTo(type, content); + } +} + +/** + * Concatenate an array of data of the given type. + * @param {String} type the type of the data in the given array. + * @param {Array} dataArray the array containing the data chunks to concatenate + * @return {String|Uint8Array|Buffer} the concatenated data + * @throws Error if the asked type is unsupported + */ +function concat (type, dataArray) { + var i, index = 0, res = null, totalLength = 0; + for(i = 0; i < dataArray.length; i++) { + totalLength += dataArray[i].length; + } + switch(type) { + case "string": + return dataArray.join(""); + case "array": + return Array.prototype.concat.apply([], dataArray); + case "uint8array": + res = new Uint8Array(totalLength); + for(i = 0; i < dataArray.length; i++) { + res.set(dataArray[i], index); + index += dataArray[i].length; + } + return res; + case "nodebuffer": + return Buffer.concat(dataArray); + default: + throw new Error("concat : unsupported type '" + type + "'"); + } +} + +/** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {StreamHelper} helper the helper to use. + * @param {Function} updateCallback a callback called on each update. Called + * with one arg : + * - the metadata linked to the update received. + * @return Promise the promise for the accumulation. + */ +function accumulate(helper, updateCallback) { + return new external.Promise(function (resolve, reject){ + var dataArray = []; + var chunkType = helper._internalType, + resultType = helper._outputType, + mimeType = helper._mimeType; + helper + .on('data', function (data, meta) { + dataArray.push(data); + if(updateCallback) { + updateCallback(meta); + } + }) + .on('error', function(err) { + dataArray = []; + reject(err); + }) + .on('end', function (){ + try { + var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); + resolve(result); + } catch (e) { + reject(e); + } + dataArray = []; + }) + .resume(); + }); +} + +/** + * An helper to easily use workers outside of JSZip. + * @constructor + * @param {Worker} worker the worker to wrap + * @param {String} outputType the type of data expected by the use + * @param {String} mimeType the mime type of the content, if applicable. + */ +function StreamHelper(worker, outputType, mimeType) { + var internalType = outputType; + switch(outputType) { + case "blob": + case "arraybuffer": + internalType = "uint8array"; + break; + case "base64": + internalType = "string"; + break; + } + + try { + // the type used internally + this._internalType = internalType; + // the type used to output results + this._outputType = outputType; + // the mime type + this._mimeType = mimeType; + utils.checkSupport(internalType); + this._worker = worker.pipe(new ConvertWorker(internalType)); + // the last workers can be rewired without issues but we need to + // prevent any updates on previous workers. + worker.lock(); + } catch(e) { + this._worker = new GenericWorker("error"); + this._worker.error(e); + } +} + +StreamHelper.prototype = { + /** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {Function} updateCb the update callback. + * @return Promise the promise for the accumulation. + */ + accumulate : function (updateCb) { + return accumulate(this, updateCb); + }, + /** + * Add a listener on an event triggered on a stream. + * @param {String} evt the name of the event + * @param {Function} fn the listener + * @return {StreamHelper} the current helper. + */ + on : function (evt, fn) { + var self = this; + + if(evt === "data") { + this._worker.on(evt, function (chunk) { + fn.call(self, chunk.data, chunk.meta); + }); + } else { + this._worker.on(evt, function () { + utils.delay(fn, arguments, self); + }); + } + return this; + }, + /** + * Resume the flow of chunks. + * @return {StreamHelper} the current helper. + */ + resume : function () { + utils.delay(this._worker.resume, [], this._worker); + return this; + }, + /** + * Pause the flow of chunks. + * @return {StreamHelper} the current helper. + */ + pause : function () { + this._worker.pause(); + return this; + }, + /** + * Return a nodejs stream for this helper. + * @param {Function} updateCb the update callback. + * @return {NodejsStreamOutputAdapter} the nodejs stream. + */ + toNodejsStream : function (updateCb) { + utils.checkSupport("nodestream"); + if (this._outputType !== "nodebuffer") { + // an object stream containing blob/arraybuffer/uint8array/string + // is strange and I don't know if it would be useful. + // I you find this comment and have a good usecase, please open a + // bug report ! + throw new Error(this._outputType + " is not supported by this method"); + } + + return new NodejsStreamOutputAdapter(this, { + objectMode : this._outputType !== "nodebuffer" + }, updateCb); + } +}; + + +module.exports = StreamHelper; + +},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(require,module,exports){ +'use strict'; + +exports.base64 = true; +exports.array = true; +exports.string = true; +exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; +exports.nodebuffer = typeof Buffer !== "undefined"; +// contains true if JSZip can read/generate Uint8Array, false otherwise. +exports.uint8array = typeof Uint8Array !== "undefined"; + +if (typeof ArrayBuffer === "undefined") { + exports.blob = false; +} +else { + var buffer = new ArrayBuffer(0); + try { + exports.blob = new Blob([buffer], { + type: "application/zip" + }).size === 0; + } + catch (e) { + try { + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + exports.blob = builder.getBlob('application/zip').size === 0; + } + catch (e) { + exports.blob = false; + } + } +} + +try { + exports.nodestream = !!require('readable-stream').Readable; +} catch(e) { + exports.nodestream = false; +} + +},{"readable-stream":16}],31:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var support = require('./support'); +var nodejsUtils = require('./nodejsUtils'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * The following functions come from pako, from pako/lib/utils/strings + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new Array(256); +for (var i=0; i<256; i++) { + _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); +} +_utf8len[254]=_utf8len[254]=1; // Invalid sequence start + +// convert string to array (typed, when possible) +var string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + if (support.uint8array) { + buf = new Uint8Array(buf_len); + } else { + buf = new Array(buf_len); + } + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +var utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +// convert array to string +var buf2string = function (buf) { + var str, i, out, c, c_len; + var len = buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + // shrinkBuf(utf16buf, out) + if (utf16buf.length !== out) { + if(utf16buf.subarray) { + utf16buf = utf16buf.subarray(0, out); + } else { + utf16buf.length = out; + } + } + + // return String.fromCharCode.apply(null, utf16buf); + return utils.applyFromCharCode(utf16buf); +}; + + +// That's all for the pako functions. + + +/** + * Transform a javascript string into an array (typed if possible) of bytes, + * UTF-8 encoded. + * @param {String} str the string to encode + * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. + */ +exports.utf8encode = function utf8encode(str) { + if (support.nodebuffer) { + return nodejsUtils.newBufferFrom(str, "utf-8"); + } + + return string2buf(str); +}; + + +/** + * Transform a bytes array (or a representation) representing an UTF-8 encoded + * string into a javascript string. + * @param {Array|Uint8Array|Buffer} buf the data de decode + * @return {String} the decoded string. + */ +exports.utf8decode = function utf8decode(buf) { + if (support.nodebuffer) { + return utils.transformTo("nodebuffer", buf).toString("utf-8"); + } + + buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); + + return buf2string(buf); +}; + +/** + * A worker to decode utf8 encoded binary chunks into string chunks. + * @constructor + */ +function Utf8DecodeWorker() { + GenericWorker.call(this, "utf-8 decode"); + // the last bytes if a chunk didn't end with a complete codepoint. + this.leftOver = null; +} +utils.inherits(Utf8DecodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8DecodeWorker.prototype.processChunk = function (chunk) { + + var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data); + + // 1st step, re-use what's left of the previous chunk + if (this.leftOver && this.leftOver.length) { + if(support.uint8array) { + var previousData = data; + data = new Uint8Array(previousData.length + this.leftOver.length); + data.set(this.leftOver, 0); + data.set(previousData, this.leftOver.length); + } else { + data = this.leftOver.concat(data); + } + this.leftOver = null; + } + + var nextBoundary = utf8border(data); + var usableData = data; + if (nextBoundary !== data.length) { + if (support.uint8array) { + usableData = data.subarray(0, nextBoundary); + this.leftOver = data.subarray(nextBoundary, data.length); + } else { + usableData = data.slice(0, nextBoundary); + this.leftOver = data.slice(nextBoundary, data.length); + } + } + + this.push({ + data : exports.utf8decode(usableData), + meta : chunk.meta + }); +}; + +/** + * @see GenericWorker.flush + */ +Utf8DecodeWorker.prototype.flush = function () { + if(this.leftOver && this.leftOver.length) { + this.push({ + data : exports.utf8decode(this.leftOver), + meta : {} + }); + this.leftOver = null; + } +}; +exports.Utf8DecodeWorker = Utf8DecodeWorker; + +/** + * A worker to endcode string chunks into utf8 encoded binary chunks. + * @constructor + */ +function Utf8EncodeWorker() { + GenericWorker.call(this, "utf-8 encode"); +} +utils.inherits(Utf8EncodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8EncodeWorker.prototype.processChunk = function (chunk) { + this.push({ + data : exports.utf8encode(chunk.data), + meta : chunk.meta + }); +}; +exports.Utf8EncodeWorker = Utf8EncodeWorker; + +},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){ +'use strict'; + +var support = require('./support'); +var base64 = require('./base64'); +var nodejsUtils = require('./nodejsUtils'); +var setImmediate = require('core-js/library/fn/set-immediate'); +var external = require("./external"); + + +/** + * Convert a string that pass as a "binary string": it should represent a byte + * array but may have > 255 char codes. Be sure to take only the first byte + * and returns the byte array. + * @param {String} str the string to transform. + * @return {Array|Uint8Array} the string in a binary format. + */ +function string2binary(str) { + var result = null; + if (support.uint8array) { + result = new Uint8Array(str.length); + } else { + result = new Array(str.length); + } + return stringToArrayLike(str, result); +} + +/** + * Create a new blob with the given content and the given type. + * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use + * an Uint8Array because the stock browser of android 4 won't accept it (it + * will be silently converted to a string, "[object Uint8Array]"). + * + * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: + * when a large amount of Array is used to create the Blob, the amount of + * memory consumed is nearly 100 times the original data amount. + * + * @param {String} type the mime type of the blob. + * @return {Blob} the created blob. + */ +exports.newBlob = function(part, type) { + exports.checkSupport("blob"); + + try { + // Blob constructor + return new Blob([part], { + type: type + }); + } + catch (e) { + + try { + // deprecated, browser only, old way + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(part); + return builder.getBlob(type); + } + catch (e) { + + // well, fuck ?! + throw new Error("Bug : can't construct the Blob."); + } + } + + +}; +/** + * The identity function. + * @param {Object} input the input. + * @return {Object} the same input. + */ +function identity(input) { + return input; +} + +/** + * Fill in an array with a string. + * @param {String} str the string to use. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. + */ +function stringToArrayLike(str, array) { + for (var i = 0; i < str.length; ++i) { + array[i] = str.charCodeAt(i) & 0xFF; + } + return array; +} + +/** + * An helper for the function arrayLikeToString. + * This contains static informations and functions that + * can be optimized by the browser JIT compiler. + */ +var arrayToStringHelper = { + /** + * Transform an array of int into a string, chunk by chunk. + * See the performances notes on arrayLikeToString. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @param {String} type the type of the array. + * @param {Integer} chunk the chunk size. + * @return {String} the resulting string. + * @throws Error if the chunk is too big for the stack. + */ + stringifyByChunk: function(array, type, chunk) { + var result = [], k = 0, len = array.length; + // shortcut + if (len <= chunk) { + return String.fromCharCode.apply(null, array); + } + while (k < len) { + if (type === "array" || type === "nodebuffer") { + result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); + } + else { + result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); + } + k += chunk; + } + return result.join(""); + }, + /** + * Call String.fromCharCode on every item in the array. + * This is the naive implementation, which generate A LOT of intermediate string. + * This should be used when everything else fail. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ + stringifyByChar: function(array){ + var resultStr = ""; + for(var i = 0; i < array.length; i++) { + resultStr += String.fromCharCode(array[i]); + } + return resultStr; + }, + applyCanBeUsed : { + /** + * true if the browser accepts to use String.fromCharCode on Uint8Array + */ + uint8array : (function () { + try { + return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; + } catch (e) { + return false; + } + })(), + /** + * true if the browser accepts to use String.fromCharCode on nodejs Buffer. + */ + nodebuffer : (function () { + try { + return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; + } catch (e) { + return false; + } + })() + } +}; + +/** + * Transform an array-like object to a string. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ +function arrayLikeToString(array) { + // Performances notes : + // -------------------- + // String.fromCharCode.apply(null, array) is the fastest, see + // see http://jsperf.com/converting-a-uint8array-to-a-string/2 + // but the stack is limited (and we can get huge arrays !). + // + // result += String.fromCharCode(array[i]); generate too many strings ! + // + // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 + // TODO : we now have workers that split the work. Do we still need that ? + var chunk = 65536, + type = exports.getTypeOf(array), + canUseApply = true; + if (type === "uint8array") { + canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; + } else if (type === "nodebuffer") { + canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; + } + + if (canUseApply) { + while (chunk > 1) { + try { + return arrayToStringHelper.stringifyByChunk(array, type, chunk); + } catch (e) { + chunk = Math.floor(chunk / 2); + } + } + } + + // no apply or chunk error : slow and painful algorithm + // default browser on android 4.* + return arrayToStringHelper.stringifyByChar(array); +} + +exports.applyFromCharCode = arrayLikeToString; + + +/** + * Copy the data from an array-like to an other array-like. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. + */ +function arrayLikeToArrayLike(arrayFrom, arrayTo) { + for (var i = 0; i < arrayFrom.length; i++) { + arrayTo[i] = arrayFrom[i]; + } + return arrayTo; +} + +// a matrix containing functions to transform everything into everything. +var transform = {}; + +// string to ? +transform["string"] = { + "string": identity, + "array": function(input) { + return stringToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["string"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return stringToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": function(input) { + return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); + } +}; + +// array to ? +transform["array"] = { + "string": arrayLikeToString, + "array": identity, + "arraybuffer": function(input) { + return (new Uint8Array(input)).buffer; + }, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// arraybuffer to ? +transform["arraybuffer"] = { + "string": function(input) { + return arrayLikeToString(new Uint8Array(input)); + }, + "array": function(input) { + return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); + }, + "arraybuffer": identity, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(new Uint8Array(input)); + } +}; + +// uint8array to ? +transform["uint8array"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return input.buffer; + }, + "uint8array": identity, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// nodebuffer to ? +transform["nodebuffer"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["nodebuffer"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return arrayLikeToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": identity +}; + +/** + * Transform an input into any type. + * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. + * If no output type is specified, the unmodified input will be returned. + * @param {String} outputType the output type. + * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. + * @throws {Error} an Error if the browser doesn't support the requested output type. + */ +exports.transformTo = function(outputType, input) { + if (!input) { + // undefined, null, etc + // an empty string won't harm. + input = ""; + } + if (!outputType) { + return input; + } + exports.checkSupport(outputType); + var inputType = exports.getTypeOf(input); + var result = transform[inputType][outputType](input); + return result; +}; + +/** + * Return the type of the input. + * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. + * @param {Object} input the input to identify. + * @return {String} the (lowercase) type of the input. + */ +exports.getTypeOf = function(input) { + if (typeof input === "string") { + return "string"; + } + if (Object.prototype.toString.call(input) === "[object Array]") { + return "array"; + } + if (support.nodebuffer && nodejsUtils.isBuffer(input)) { + return "nodebuffer"; + } + if (support.uint8array && input instanceof Uint8Array) { + return "uint8array"; + } + if (support.arraybuffer && input instanceof ArrayBuffer) { + return "arraybuffer"; + } +}; + +/** + * Throw an exception if the type is not supported. + * @param {String} type the type to check. + * @throws {Error} an Error if the browser doesn't support the requested type. + */ +exports.checkSupport = function(type) { + var supported = support[type.toLowerCase()]; + if (!supported) { + throw new Error(type + " is not supported by this platform"); + } +}; + +exports.MAX_VALUE_16BITS = 65535; +exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 + +/** + * Prettify a string read as binary. + * @param {string} str the string to prettify. + * @return {string} a pretty string. + */ +exports.pretty = function(str) { + var res = '', + code, i; + for (i = 0; i < (str || "").length; i++) { + code = str.charCodeAt(i); + res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); + } + return res; +}; + +/** + * Defer the call of a function. + * @param {Function} callback the function to call asynchronously. + * @param {Array} args the arguments to give to the callback. + */ +exports.delay = function(callback, args, self) { + setImmediate(function () { + callback.apply(self || null, args || []); + }); +}; + +/** + * Extends a prototype with an other, without calling a constructor with + * side effects. Inspired by nodejs' `utils.inherits` + * @param {Function} ctor the constructor to augment + * @param {Function} superCtor the parent constructor to use + */ +exports.inherits = function (ctor, superCtor) { + var Obj = function() {}; + Obj.prototype = superCtor.prototype; + ctor.prototype = new Obj(); +}; + +/** + * Merge the objects passed as parameters into a new one. + * @private + * @param {...Object} var_args All objects to merge. + * @return {Object} a new object with the data of the others. + */ +exports.extend = function() { + var result = {}, i, attr; + for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers + for (attr in arguments[i]) { + if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { + result[attr] = arguments[i][attr]; + } + } + } + return result; +}; + +/** + * Transform arbitrary content into a Promise. + * @param {String} name a name for the content being processed. + * @param {Object} inputData the content to process. + * @param {Boolean} isBinary true if the content is not an unicode string + * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. + * @param {Boolean} isBase64 true if the string content is encoded with base64. + * @return {Promise} a promise in a format usable by JSZip. + */ +exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { + + // if inputData is already a promise, this flatten it. + var promise = external.Promise.resolve(inputData).then(function(data) { + + + var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); + + if (isBlob && typeof FileReader !== "undefined") { + return new external.Promise(function (resolve, reject) { + var reader = new FileReader(); + + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e.target.error); + }; + reader.readAsArrayBuffer(data); + }); + } else { + return data; + } + }); + + return promise.then(function(data) { + var dataType = exports.getTypeOf(data); + + if (!dataType) { + return external.Promise.reject( + new Error("Can't read the data of '" + name + "'. Is it " + + "in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") + ); + } + // special case : it's way easier to work with Uint8Array than with ArrayBuffer + if (dataType === "arraybuffer") { + data = exports.transformTo("uint8array", data); + } else if (dataType === "string") { + if (isBase64) { + data = base64.decode(data); + } + else if (isBinary) { + // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask + if (isOptimizedBinaryString !== true) { + // this is a string, not in a base64 format. + // Be sure that this is a correct "binary string" + data = string2binary(data); + } + } + } + return data; + }); +}; + +},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"core-js/library/fn/set-immediate":36}],33:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var sig = require('./signature'); +var ZipEntry = require('./zipEntry'); +var utf8 = require('./utf8'); +var support = require('./support'); +// class ZipEntries {{{ +/** + * All the entries in the zip file. + * @constructor + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntries(loadOptions) { + this.files = []; + this.loadOptions = loadOptions; +} +ZipEntries.prototype = { + /** + * Check that the reader is on the specified signature. + * @param {string} expectedSignature the expected signature. + * @throws {Error} if it is an other signature. + */ + checkSignature: function(expectedSignature) { + if (!this.reader.readAndCheckSignature(expectedSignature)) { + this.reader.index -= 4; + var signature = this.reader.readString(4); + throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); + } + }, + /** + * Check if the given signature is at the given index. + * @param {number} askedIndex the index to check. + * @param {string} expectedSignature the signature to expect. + * @return {boolean} true if the signature is here, false otherwise. + */ + isSignature: function(askedIndex, expectedSignature) { + var currentIndex = this.reader.index; + this.reader.setIndex(askedIndex); + var signature = this.reader.readString(4); + var result = signature === expectedSignature; + this.reader.setIndex(currentIndex); + return result; + }, + /** + * Read the end of the central directory. + */ + readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2); + this.diskWithCentralDirStart = this.reader.readInt(2); + this.centralDirRecordsOnThisDisk = this.reader.readInt(2); + this.centralDirRecords = this.reader.readInt(2); + this.centralDirSize = this.reader.readInt(4); + this.centralDirOffset = this.reader.readInt(4); + + this.zipCommentLength = this.reader.readInt(2); + // warning : the encoding depends of the system locale + // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. + // On a windows machine, this field is encoded with the localized windows code page. + var zipComment = this.reader.readData(this.zipCommentLength); + var decodeParamType = support.uint8array ? "uint8array" : "array"; + // To get consistent behavior with the generation part, we will assume that + // this is utf8 encoded unless specified otherwise. + var decodeContent = utils.transformTo(decodeParamType, zipComment); + this.zipComment = this.loadOptions.decodeFileName(decodeContent); + }, + /** + * Read the end of the Zip 64 central directory. + * Not merged with the method readEndOfCentral : + * The end of central can coexist with its Zip64 brother, + * I don't want to read the wrong number of bytes ! + */ + readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8); + this.reader.skip(4); + // this.versionMadeBy = this.reader.readString(2); + // this.versionNeeded = this.reader.readInt(2); + this.diskNumber = this.reader.readInt(4); + this.diskWithCentralDirStart = this.reader.readInt(4); + this.centralDirRecordsOnThisDisk = this.reader.readInt(8); + this.centralDirRecords = this.reader.readInt(8); + this.centralDirSize = this.reader.readInt(8); + this.centralDirOffset = this.reader.readInt(8); + + this.zip64ExtensibleData = {}; + var extraDataSize = this.zip64EndOfCentralSize - 44, + index = 0, + extraFieldId, + extraFieldLength, + extraFieldValue; + while (index < extraDataSize) { + extraFieldId = this.reader.readInt(2); + extraFieldLength = this.reader.readInt(4); + extraFieldValue = this.reader.readData(extraFieldLength); + this.zip64ExtensibleData[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Read the end of the Zip 64 central directory locator. + */ + readBlockZip64EndOfCentralLocator: function() { + this.diskWithZip64CentralDirStart = this.reader.readInt(4); + this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); + this.disksCount = this.reader.readInt(4); + if (this.disksCount > 1) { + throw new Error("Multi-volumes zip are not supported"); + } + }, + /** + * Read the local files, based on the offset read in the central part. + */ + readLocalFiles: function() { + var i, file; + for (i = 0; i < this.files.length; i++) { + file = this.files[i]; + this.reader.setIndex(file.localHeaderOffset); + this.checkSignature(sig.LOCAL_FILE_HEADER); + file.readLocalPart(this.reader); + file.handleUTF8(); + file.processAttributes(); + } + }, + /** + * Read the central directory. + */ + readCentralDir: function() { + var file; + + this.reader.setIndex(this.centralDirOffset); + while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) { + file = new ZipEntry({ + zip64: this.zip64 + }, this.loadOptions); + file.readCentralPart(this.reader); + this.files.push(file); + } + + if (this.centralDirRecords !== this.files.length) { + if (this.centralDirRecords !== 0 && this.files.length === 0) { + // We expected some records but couldn't find ANY. + // This is really suspicious, as if something went wrong. + throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); + } else { + // We found some records but not all. + // Something is wrong but we got something for the user: no error here. + // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length); + } + } + }, + /** + * Read the end of central directory. + */ + readEndOfCentral: function() { + var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); + if (offset < 0) { + // Check if the content is a truncated zip or complete garbage. + // A "LOCAL_FILE_HEADER" is not required at the beginning (auto + // extractible zip for example) but it can give a good hint. + // If an ajax request was used without responseType, we will also + // get unreadable data. + var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER); + + if (isGarbage) { + throw new Error("Can't find end of central directory : is this a zip file ? " + + "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"); + } else { + throw new Error("Corrupted zip: can't find end of central directory"); + } + + } + this.reader.setIndex(offset); + var endOfCentralDirOffset = offset; + this.checkSignature(sig.CENTRAL_DIRECTORY_END); + this.readBlockEndOfCentral(); + + + /* extract from the zip spec : + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + */ + if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { + this.zip64 = true; + + /* + Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from + the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents + all numbers as 64-bit double precision IEEE 754 floating point numbers. + So, we have 53bits for integers and bitwise operations treat everything as 32bits. + see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators + and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 + */ + + // should look for a zip64 EOCD locator + offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + if (offset < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + this.readBlockZip64EndOfCentralLocator(); + + // now the zip64 EOCD record + if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) { + // console.warn("ZIP64 end of central directory not where expected."); + this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + if (this.relativeOffsetEndOfZip64CentralDir < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); + } + } + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + this.readBlockZip64EndOfCentral(); + } + + var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize; + if (this.zip64) { + expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator + expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize; + } + + var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset; + + if (extraBytes > 0) { + // console.warn(extraBytes, "extra bytes at beginning or within zipfile"); + if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) { + // The offsets seem wrong, but we have something at the specified offset. + // So… we keep it. + } else { + // the offset is wrong, update the "zero" of the reader + // this happens if data has been prepended (crx files for example) + this.reader.zero = extraBytes; + } + } else if (extraBytes < 0) { + throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes."); + } + }, + prepareReader: function(data) { + this.reader = readerFor(data); + }, + /** + * Read a zip file and create ZipEntries. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. + */ + load: function(data) { + this.prepareReader(data); + this.readEndOfCentral(); + this.readCentralDir(); + this.readLocalFiles(); + } +}; +// }}} end of ZipEntries +module.exports = ZipEntries; + +},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var CompressedObject = require('./compressedObject'); +var crc32fn = require('./crc32'); +var utf8 = require('./utf8'); +var compressions = require('./compressions'); +var support = require('./support'); + +var MADE_BY_DOS = 0x00; +var MADE_BY_UNIX = 0x03; + +/** + * Find a compression registered in JSZip. + * @param {string} compressionMethod the method magic to find. + * @return {Object|null} the JSZip compression object, null if none found. + */ +var findCompression = function(compressionMethod) { + for (var method in compressions) { + if (!compressions.hasOwnProperty(method)) { + continue; + } + if (compressions[method].magic === compressionMethod) { + return compressions[method]; + } + } + return null; +}; + +// class ZipEntry {{{ +/** + * An entry in the zip file. + * @constructor + * @param {Object} options Options of the current file. + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntry(options, loadOptions) { + this.options = options; + this.loadOptions = loadOptions; +} +ZipEntry.prototype = { + /** + * say if the file is encrypted. + * @return {boolean} true if the file is encrypted, false otherwise. + */ + isEncrypted: function() { + // bit 1 is set + return (this.bitFlag & 0x0001) === 0x0001; + }, + /** + * say if the file has utf-8 filename/comment. + * @return {boolean} true if the filename/comment is in utf-8, false otherwise. + */ + useUTF8: function() { + // bit 11 is set + return (this.bitFlag & 0x0800) === 0x0800; + }, + /** + * Read the local part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readLocalPart: function(reader) { + var compression, localExtraFieldsLength; + + // we already know everything from the central dir ! + // If the central dir data are false, we are doomed. + // On the bright side, the local part is scary : zip64, data descriptors, both, etc. + // The less data we get here, the more reliable this should be. + // Let's skip the whole header and dash to the data ! + reader.skip(22); + // in some zip created on windows, the filename stored in the central dir contains \ instead of /. + // Strangely, the filename here is OK. + // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes + // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... + // Search "unzip mismatching "local" filename continuing with "central" filename version" on + // the internet. + // + // I think I see the logic here : the central directory is used to display + // content and the local directory is used to extract the files. Mixing / and \ + // may be used to display \ to windows users and use / when extracting the files. + // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 + this.fileNameLength = reader.readInt(2); + localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir + // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding. + this.fileName = reader.readData(this.fileNameLength); + reader.skip(localExtraFieldsLength); + + if (this.compressedSize === -1 || this.uncompressedSize === -1) { + throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)"); + } + + compression = findCompression(this.compressionMethod); + if (compression === null) { // no compression found + throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")"); + } + this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize)); + }, + + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readCentralPart: function(reader) { + this.versionMadeBy = reader.readInt(2); + reader.skip(2); + // this.versionNeeded = reader.readInt(2); + this.bitFlag = reader.readInt(2); + this.compressionMethod = reader.readString(2); + this.date = reader.readDate(); + this.crc32 = reader.readInt(4); + this.compressedSize = reader.readInt(4); + this.uncompressedSize = reader.readInt(4); + var fileNameLength = reader.readInt(2); + this.extraFieldsLength = reader.readInt(2); + this.fileCommentLength = reader.readInt(2); + this.diskNumberStart = reader.readInt(2); + this.internalFileAttributes = reader.readInt(2); + this.externalFileAttributes = reader.readInt(4); + this.localHeaderOffset = reader.readInt(4); + + if (this.isEncrypted()) { + throw new Error("Encrypted zip are not supported"); + } + + // will be read in the local part, see the comments there + reader.skip(fileNameLength); + this.readExtraFields(reader); + this.parseZIP64ExtraField(reader); + this.fileComment = reader.readData(this.fileCommentLength); + }, + + /** + * Parse the external file attributes and get the unix/dos permissions. + */ + processAttributes: function () { + this.unixPermissions = null; + this.dosPermissions = null; + var madeBy = this.versionMadeBy >> 8; + + // Check if we have the DOS directory flag set. + // We look for it in the DOS and UNIX permissions + // but some unknown platform could set it as a compatibility flag. + this.dir = this.externalFileAttributes & 0x0010 ? true : false; + + if(madeBy === MADE_BY_DOS) { + // first 6 bits (0 to 5) + this.dosPermissions = this.externalFileAttributes & 0x3F; + } + + if(madeBy === MADE_BY_UNIX) { + this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; + // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); + } + + // fail safe : if the name ends with a / it probably means a folder + if (!this.dir && this.fileNameStr.slice(-1) === '/') { + this.dir = true; + } + }, + + /** + * Parse the ZIP64 extra field and merge the info in the current ZipEntry. + * @param {DataReader} reader the reader to use. + */ + parseZIP64ExtraField: function(reader) { + + if (!this.extraFields[0x0001]) { + return; + } + + // should be something, preparing the extra reader + var extraReader = readerFor(this.extraFields[0x0001].value); + + // I really hope that these 64bits integer can fit in 32 bits integer, because js + // won't let us have more. + if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { + this.uncompressedSize = extraReader.readInt(8); + } + if (this.compressedSize === utils.MAX_VALUE_32BITS) { + this.compressedSize = extraReader.readInt(8); + } + if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { + this.localHeaderOffset = extraReader.readInt(8); + } + if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { + this.diskNumberStart = extraReader.readInt(4); + } + }, + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readExtraFields: function(reader) { + var end = reader.index + this.extraFieldsLength, + extraFieldId, + extraFieldLength, + extraFieldValue; + + if (!this.extraFields) { + this.extraFields = {}; + } + + while (reader.index < end) { + extraFieldId = reader.readInt(2); + extraFieldLength = reader.readInt(2); + extraFieldValue = reader.readData(extraFieldLength); + + this.extraFields[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Apply an UTF8 transformation if needed. + */ + handleUTF8: function() { + var decodeParamType = support.uint8array ? "uint8array" : "array"; + if (this.useUTF8()) { + this.fileNameStr = utf8.utf8decode(this.fileName); + this.fileCommentStr = utf8.utf8decode(this.fileComment); + } else { + var upath = this.findExtraFieldUnicodePath(); + if (upath !== null) { + this.fileNameStr = upath; + } else { + // ASCII text or unsupported code page + var fileNameByteArray = utils.transformTo(decodeParamType, this.fileName); + this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray); + } + + var ucomment = this.findExtraFieldUnicodeComment(); + if (ucomment !== null) { + this.fileCommentStr = ucomment; + } else { + // ASCII text or unsupported code page + var commentByteArray = utils.transformTo(decodeParamType, this.fileComment); + this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray); + } + } + }, + + /** + * Find the unicode path declared in the extra field, if any. + * @return {String} the unicode path, null otherwise. + */ + findExtraFieldUnicodePath: function() { + var upathField = this.extraFields[0x7075]; + if (upathField) { + var extraReader = readerFor(upathField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the filename changed, this field is out of date. + if (crc32fn(this.fileName) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(upathField.length - 5)); + } + return null; + }, + + /** + * Find the unicode comment declared in the extra field, if any. + * @return {String} the unicode comment, null otherwise. + */ + findExtraFieldUnicodeComment: function() { + var ucommentField = this.extraFields[0x6375]; + if (ucommentField) { + var extraReader = readerFor(ucommentField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the comment changed, this field is out of date. + if (crc32fn(this.fileComment) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(ucommentField.length - 5)); + } + return null; + } +}; +module.exports = ZipEntry; + +},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(require,module,exports){ +'use strict'; + +var StreamHelper = require('./stream/StreamHelper'); +var DataWorker = require('./stream/DataWorker'); +var utf8 = require('./utf8'); +var CompressedObject = require('./compressedObject'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * A simple object representing a file in the zip file. + * @constructor + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data + * @param {Object} options the options of the file + */ +var ZipObject = function(name, data, options) { + this.name = name; + this.dir = options.dir; + this.date = options.date; + this.comment = options.comment; + this.unixPermissions = options.unixPermissions; + this.dosPermissions = options.dosPermissions; + + this._data = data; + this._dataBinary = options.binary; + // keep only the compression + this.options = { + compression : options.compression, + compressionOptions : options.compressionOptions + }; +}; + +ZipObject.prototype = { + /** + * Create an internal stream for the content of this object. + * @param {String} type the type of each chunk. + * @return StreamHelper the stream. + */ + internalStream: function (type) { + var result = null, outputType = "string"; + try { + if (!type) { + throw new Error("No output type specified."); + } + outputType = type.toLowerCase(); + var askUnicodeString = outputType === "string" || outputType === "text"; + if (outputType === "binarystring" || outputType === "text") { + outputType = "string"; + } + result = this._decompressWorker(); + + var isUnicodeString = !this._dataBinary; + + if (isUnicodeString && !askUnicodeString) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + if (!isUnicodeString && askUnicodeString) { + result = result.pipe(new utf8.Utf8DecodeWorker()); + } + } catch (e) { + result = new GenericWorker("error"); + result.error(e); + } + + return new StreamHelper(result, outputType, ""); + }, + + /** + * Prepare the content in the asked type. + * @param {String} type the type of the result. + * @param {Function} onUpdate a function to call on each internal update. + * @return Promise the promise of the result. + */ + async: function (type, onUpdate) { + return this.internalStream(type).accumulate(onUpdate); + }, + + /** + * Prepare the content as a nodejs stream. + * @param {String} type the type of each chunk. + * @param {Function} onUpdate a function to call on each internal update. + * @return Stream the stream. + */ + nodeStream: function (type, onUpdate) { + return this.internalStream(type || "nodebuffer").toNodejsStream(onUpdate); + }, + + /** + * Return a worker for the compressed content. + * @private + * @param {Object} compression the compression object to use. + * @param {Object} compressionOptions the options to use when compressing. + * @return Worker the worker. + */ + _compressWorker: function (compression, compressionOptions) { + if ( + this._data instanceof CompressedObject && + this._data.compression.magic === compression.magic + ) { + return this._data.getCompressedWorker(); + } else { + var result = this._decompressWorker(); + if(!this._dataBinary) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + return CompressedObject.createWorkerFrom(result, compression, compressionOptions); + } + }, + /** + * Return a worker for the decompressed content. + * @private + * @return Worker the worker. + */ + _decompressWorker : function () { + if (this._data instanceof CompressedObject) { + return this._data.getContentWorker(); + } else if (this._data instanceof GenericWorker) { + return this._data; + } else { + return new DataWorker(this._data); + } + } +}; + +var removedMethods = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"]; +var removedFn = function () { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); +}; + +for(var i = 0; i < removedMethods.length; i++) { + ZipObject.prototype[removedMethods[i]] = removedFn; +} +module.exports = ZipObject; + +},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(require,module,exports){ +require('../modules/web.immediate'); +module.exports = require('../modules/_core').setImmediate; +},{"../modules/_core":40,"../modules/web.immediate":56}],37:[function(require,module,exports){ +module.exports = function(it){ + if(typeof it != 'function')throw TypeError(it + ' is not a function!'); + return it; +}; +},{}],38:[function(require,module,exports){ +var isObject = require('./_is-object'); +module.exports = function(it){ + if(!isObject(it))throw TypeError(it + ' is not an object!'); + return it; +}; +},{"./_is-object":51}],39:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = function(it){ + return toString.call(it).slice(8, -1); +}; +},{}],40:[function(require,module,exports){ +var core = module.exports = {version: '2.3.0'}; +if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef +},{}],41:[function(require,module,exports){ +// optional / simple context binding +var aFunction = require('./_a-function'); +module.exports = function(fn, that, length){ + aFunction(fn); + if(that === undefined)return fn; + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; +}; +},{"./_a-function":37}],42:[function(require,module,exports){ +// Thank's IE8 for his funny defineProperty +module.exports = !require('./_fails')(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_fails":45}],43:[function(require,module,exports){ +var isObject = require('./_is-object') + , document = require('./_global').document + // in old IE typeof document.createElement is 'object' + , is = isObject(document) && isObject(document.createElement); +module.exports = function(it){ + return is ? document.createElement(it) : {}; +}; +},{"./_global":46,"./_is-object":51}],44:[function(require,module,exports){ +var global = require('./_global') + , core = require('./_core') + , ctx = require('./_ctx') + , hide = require('./_hide') + , PROTOTYPE = 'prototype'; + +var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , IS_WRAP = type & $export.W + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] + , key, own, out; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if(own && key in exports)continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function(C){ + var F = function(a, b, c){ + if(this instanceof C){ + switch(arguments.length){ + case 0: return new C; + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if(IS_PROTO){ + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); + } + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; +},{"./_core":40,"./_ctx":41,"./_global":46,"./_hide":47}],45:[function(require,module,exports){ +module.exports = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } +}; +},{}],46:[function(require,module,exports){ +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); +if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef +},{}],47:[function(require,module,exports){ +var dP = require('./_object-dp') + , createDesc = require('./_property-desc'); +module.exports = require('./_descriptors') ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); +} : function(object, key, value){ + object[key] = value; + return object; +}; +},{"./_descriptors":42,"./_object-dp":52,"./_property-desc":53}],48:[function(require,module,exports){ +module.exports = require('./_global').document && document.documentElement; +},{"./_global":46}],49:[function(require,module,exports){ +module.exports = !require('./_descriptors') && !require('./_fails')(function(){ + return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_descriptors":42,"./_dom-create":43,"./_fails":45}],50:[function(require,module,exports){ +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function(fn, args, that){ + var un = that === undefined; + switch(args.length){ + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; +},{}],51:[function(require,module,exports){ +module.exports = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; +},{}],52:[function(require,module,exports){ +var anObject = require('./_an-object') + , IE8_DOM_DEFINE = require('./_ie8-dom-define') + , toPrimitive = require('./_to-primitive') + , dP = Object.defineProperty; + +exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){ + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if(IE8_DOM_DEFINE)try { + return dP(O, P, Attributes); + } catch(e){ /* empty */ } + if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); + if('value' in Attributes)O[P] = Attributes.value; + return O; +}; +},{"./_an-object":38,"./_descriptors":42,"./_ie8-dom-define":49,"./_to-primitive":55}],53:[function(require,module,exports){ +module.exports = function(bitmap, value){ + return { + enumerable : !(bitmap & 1), + configurable: !(bitmap & 2), + writable : !(bitmap & 4), + value : value + }; +}; +},{}],54:[function(require,module,exports){ +var ctx = require('./_ctx') + , invoke = require('./_invoke') + , html = require('./_html') + , cel = require('./_dom-create') + , global = require('./_global') + , process = global.process + , setTask = global.setImmediate + , clearTask = global.clearImmediate + , MessageChannel = global.MessageChannel + , counter = 0 + , queue = {} + , ONREADYSTATECHANGE = 'onreadystatechange' + , defer, channel, port; +var run = function(){ + var id = +this; + if(queue.hasOwnProperty(id)){ + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function(event){ + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if(!setTask || !clearTask){ + setTask = function setImmediate(fn){ + var args = [], i = 1; + while(arguments.length > i)args.push(arguments[i++]); + queue[++counter] = function(){ + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id){ + delete queue[id]; + }; + // Node.js 0.8- + if(require('./_cof')(process) == 'process'){ + defer = function(id){ + process.nextTick(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if(MessageChannel){ + channel = new MessageChannel; + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ + defer = function(id){ + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if(ONREADYSTATECHANGE in cel('script')){ + defer = function(id){ + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function(id){ + setTimeout(ctx(run, id, 1), 0); + }; + } +} +module.exports = { + set: setTask, + clear: clearTask +}; +},{"./_cof":39,"./_ctx":41,"./_dom-create":43,"./_global":46,"./_html":48,"./_invoke":50}],55:[function(require,module,exports){ +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = require('./_is-object'); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function(it, S){ + if(!isObject(it))return it; + var fn, val; + if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; + if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + throw TypeError("Can't convert object to primitive value"); +}; +},{"./_is-object":51}],56:[function(require,module,exports){ +var $export = require('./_export') + , $task = require('./_task'); +$export($export.G + $export.B, { + setImmediate: $task.set, + clearImmediate: $task.clear +}); +},{"./_export":44,"./_task":54}],57:[function(require,module,exports){ +(function (global){ +'use strict'; +var Mutation = global.MutationObserver || global.WebKitMutationObserver; + +var scheduleDrain; + +{ + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + scheduleDrain = function () { + element.data = (called = ++called % 2); + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + + // Create a + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
      + +
      +

      Hierarchy For All Packages

      Package Hierarchies: @@ -75,33 +99,34 @@
  • +

    Class Hierarchy

      -
    • java.lang.Object +
    • java.lang.Object
        -
      • co.aikar.commands.CommandCompletions<C> +
      • co.aikar.commands.CommandCompletions<C>
      • -
      • co.aikar.commands.CommandContexts<R> +
      • co.aikar.commands.CommandContexts<R>
      • -
      • co.aikar.commands.CommandManager<IT,I,FT,MF,CEC,CC> +
      • co.aikar.commands.CommandManager<IT,​I,​FT,​MF,​CEC,​CC> @@ -109,17 +134,21 @@
    +
    +
    + diff --git a/docs/acf-paper/package-search-index.js b/docs/acf-paper/package-search-index.js new file mode 100644 index 00000000..92674ca2 --- /dev/null +++ b/docs/acf-paper/package-search-index.js @@ -0,0 +1 @@ +packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"co.aikar.commands"}] \ No newline at end of file diff --git a/docs/acf-paper/package-search-index.zip b/docs/acf-paper/package-search-index.zip new file mode 100644 index 00000000..358a1480 Binary files /dev/null and b/docs/acf-paper/package-search-index.zip differ diff --git a/docs/acf-paper/resources/glass.png b/docs/acf-paper/resources/glass.png new file mode 100644 index 00000000..a7f591f4 Binary files /dev/null and b/docs/acf-paper/resources/glass.png differ diff --git a/docs/acf-paper/resources/x.png b/docs/acf-paper/resources/x.png new file mode 100644 index 00000000..30548a75 Binary files /dev/null and b/docs/acf-paper/resources/x.png differ diff --git a/docs/acf-paper/script.js b/docs/acf-paper/script.js index b3463569..0eaaf535 100644 --- a/docs/acf-paper/script.js +++ b/docs/acf-paper/script.js @@ -1,9 +1,114 @@ -function show(type) -{ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var moduleSearchIndex; +var packageSearchIndex; +var typeSearchIndex; +var memberSearchIndex; +var tagSearchIndex; +function loadScripts(doc, tag) { + createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); + if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || + window.navigator.userAgent.indexOf('Edge/') > 0) { + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); + } + createElem(doc, tag, 'search.js'); + + $.get(pathtoroot + "module-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + moduleSearchIndex = JSON.parse(zip.file("module-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "package-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + packageSearchIndex = JSON.parse(zip.file("package-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "type-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + typeSearchIndex = JSON.parse(zip.file("type-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "member-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + memberSearchIndex = JSON.parse(zip.file("member-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "tag-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + tagSearchIndex = JSON.parse(zip.file("tag-search-index.json").asText()); + }); + }); + if (!moduleSearchIndex) { + createElem(doc, tag, 'module-search-index.js'); + } + if (!packageSearchIndex) { + createElem(doc, tag, 'package-search-index.js'); + } + if (!typeSearchIndex) { + createElem(doc, tag, 'type-search-index.js'); + } + if (!memberSearchIndex) { + createElem(doc, tag, 'member-search-index.js'); + } + if (!tagSearchIndex) { + createElem(doc, tag, 'tag-search-index.js'); + } + $(window).resize(function() { + $('.navPadding').css('padding-top', $('.fixedNav').css("height")); + }); +} + +function createElem(doc, tag, path) { + var script = doc.createElement(tag); + var scriptElement = doc.getElementsByTagName(tag)[0]; + script.src = pathtoroot + path; + scriptElement.parentNode.insertBefore(script, scriptElement); +} + +function show(type) { count = 0; - for (var key in methods) { + for (var key in data) { var row = document.getElementById(key); - if ((methods[key] & type) != 0) { + if ((data[key] & type) !== 0) { row.style.display = ''; row.className = (count++ % 2) ? rowColor : altColor; } @@ -13,8 +118,7 @@ function show(type) updateTabs(type); } -function updateTabs(type) -{ +function updateTabs(type) { for (var value in tabs) { var sNode = document.getElementById(tabs[value][0]); var spanNode = sNode.firstChild; @@ -28,3 +132,8 @@ function updateTabs(type) } } } + +function updateModuleFrame(pFrame, cFrame) { + top.packageFrame.location = pFrame; + top.classFrame.location = cFrame; +} diff --git a/docs/acf-paper/search.js b/docs/acf-paper/search.js new file mode 100644 index 00000000..b773531b --- /dev/null +++ b/docs/acf-paper/search.js @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var noResult = {l: "No results found"}; +var catModules = "Modules"; +var catPackages = "Packages"; +var catTypes = "Types"; +var catMembers = "Members"; +var catSearchTags = "SearchTags"; +var highlight = "$&"; +var camelCaseRegexp = ""; +var secondaryMatcher = ""; +function getHighlightedText(item) { + var ccMatcher = new RegExp(camelCaseRegexp); + var label = item.replace(ccMatcher, highlight); + if (label === item) { + label = item.replace(secondaryMatcher, highlight); + } + return label; +} +function getURLPrefix(ui) { + var urlPrefix=""; + if (useModuleDirectories) { + var slash = "/"; + if (ui.item.category === catModules) { + return ui.item.l + slash; + } else if (ui.item.category === catPackages && ui.item.m) { + return ui.item.m + slash; + } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { + $.each(packageSearchIndex, function(index, item) { + if (ui.item.p == item.l) { + urlPrefix = item.m + slash; + } + }); + return urlPrefix; + } else { + return urlPrefix; + } + } + return urlPrefix; +} +var watermark = 'Search'; +$(function() { + $("#search").val(''); + $("#search").prop("disabled", false); + $("#reset").prop("disabled", false); + $("#search").val(watermark).addClass('watermark'); + $("#search").blur(function() { + if ($(this).val().length == 0) { + $(this).val(watermark).addClass('watermark'); + } + }); + $("#search").on('click keydown', function() { + if ($(this).val() == watermark) { + $(this).val('').removeClass('watermark'); + } + }); + $("#reset").click(function() { + $("#search").val(''); + $("#search").focus(); + }); + $("#search").focus(); + $("#search")[0].setSelectionRange(0, 0); +}); +$.widget("custom.catcomplete", $.ui.autocomplete, { + _create: function() { + this._super(); + this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)"); + }, + _renderMenu: function(ul, items) { + var rMenu = this, + currentCategory = ""; + rMenu.menu.bindings = $(); + $.each(items, function(index, item) { + var li; + if (item.l !== noResult.l && item.category !== currentCategory) { + ul.append("
  • " + item.category + "
  • "); + currentCategory = item.category; + } + li = rMenu._renderItemData(ul, item); + if (item.category) { + li.attr("aria-label", item.category + " : " + item.l); + li.attr("class", "resultItem"); + } else { + li.attr("aria-label", item.l); + li.attr("class", "resultItem"); + } + }); + }, + _renderItem: function(ul, item) { + var label = ""; + if (item.category === catModules) { + label = getHighlightedText(item.l); + } else if (item.category === catPackages) { + label = (item.m) + ? getHighlightedText(item.m + "/" + item.l) + : getHighlightedText(item.l); + } else if (item.category === catTypes) { + label = (item.p) + ? getHighlightedText(item.p + "." + item.l) + : getHighlightedText(item.l); + } else if (item.category === catMembers) { + label = getHighlightedText(item.p + "." + (item.c + "." + item.l)); + } else if (item.category === catSearchTags) { + label = getHighlightedText(item.l); + } else { + label = item.l; + } + var li = $("
  • ").appendTo(ul); + var div = $("
    ").appendTo(li); + if (item.category === catSearchTags) { + if (item.d) { + div.html(label + " (" + item.h + ")
    " + + item.d + "
    "); + } else { + div.html(label + " (" + item.h + ")"); + } + } else { + div.html(label); + } + return li; + } +}); +$(function() { + $("#search").catcomplete({ + minLength: 1, + delay: 100, + source: function(request, response) { + var result = new Array(); + var presult = new Array(); + var tresult = new Array(); + var mresult = new Array(); + var tgresult = new Array(); + var secondaryresult = new Array(); + var displayCount = 0; + var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i"); + camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)"); + var camelCaseMatcher = new RegExp("^" + camelCaseRegexp); + secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); + + // Return the nested innermost name from the specified object + function nestedName(e) { + return e.l.substring(e.l.lastIndexOf(".") + 1); + } + + function concatResults(a1, a2) { + a1 = a1.concat(a2); + a2.length = 0; + return a1; + } + + if (moduleSearchIndex) { + var mdleCount = 0; + $.each(moduleSearchIndex, function(index, item) { + item.category = catModules; + if (exactMatcher.test(item.l)) { + result.push(item); + mdleCount++; + } else if (camelCaseMatcher.test(item.l)) { + result.push(item); + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + displayCount = mdleCount; + result = concatResults(result, secondaryresult); + } + if (packageSearchIndex) { + var pCount = 0; + var pkg = ""; + $.each(packageSearchIndex, function(index, item) { + item.category = catPackages; + pkg = (item.m) + ? (item.m + "/" + item.l) + : item.l; + if (exactMatcher.test(item.l)) { + presult.push(item); + pCount++; + } else if (camelCaseMatcher.test(pkg)) { + presult.push(item); + } else if (secondaryMatcher.test(pkg)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(presult, secondaryresult)); + displayCount = (pCount > displayCount) ? pCount : displayCount; + } + if (typeSearchIndex) { + var tCount = 0; + $.each(typeSearchIndex, function(index, item) { + item.category = catTypes; + var s = nestedName(item); + if (exactMatcher.test(s)) { + tresult.push(item); + tCount++; + } else if (camelCaseMatcher.test(s)) { + tresult.push(item); + } else if (secondaryMatcher.test(item.p + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tresult, secondaryresult)); + displayCount = (tCount > displayCount) ? tCount : displayCount; + } + if (memberSearchIndex) { + var mCount = 0; + $.each(memberSearchIndex, function(index, item) { + item.category = catMembers; + var s = nestedName(item); + if (exactMatcher.test(s)) { + mresult.push(item); + mCount++; + } else if (camelCaseMatcher.test(s)) { + mresult.push(item); + } else if (secondaryMatcher.test(item.c + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(mresult, secondaryresult)); + displayCount = (mCount > displayCount) ? mCount : displayCount; + } + if (tagSearchIndex) { + var tgCount = 0; + $.each(tagSearchIndex, function(index, item) { + item.category = catSearchTags; + if (exactMatcher.test(item.l)) { + tgresult.push(item); + tgCount++; + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tgresult, secondaryresult)); + displayCount = (tgCount > displayCount) ? tgCount : displayCount; + } + displayCount = (displayCount > 500) ? displayCount : 500; + var counter = function() { + var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0}; + var f = function(item) { + count[item.category] += 1; + return (count[item.category] <= displayCount); + }; + return f; + }(); + response(result.filter(counter)); + }, + response: function(event, ui) { + if (!ui.content.length) { + ui.content.push(noResult); + } else { + $("#search").empty(); + } + }, + autoFocus: true, + position: { + collision: "flip" + }, + select: function(event, ui) { + if (ui.item.l !== noResult.l) { + var url = getURLPrefix(ui); + if (ui.item.category === catModules) { + if (useModuleDirectories) { + url += "module-summary.html"; + } else { + url = ui.item.l + "-summary.html"; + } + } else if (ui.item.category === catPackages) { + if (ui.item.url) { + url = ui.item.url; + } else { + url += ui.item.l.replace(/\./g, '/') + "/package-summary.html"; + } + } else if (ui.item.category === catTypes) { + if (ui.item.url) { + url = ui.item.url; + } else if (ui.item.p === "") { + url += ui.item.l + ".html"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; + } + } else if (ui.item.category === catMembers) { + if (ui.item.p === "") { + url += ui.item.c + ".html" + "#"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; + } + if (ui.item.url) { + url += ui.item.url; + } else { + url += ui.item.l; + } + } else if (ui.item.category === catSearchTags) { + url += ui.item.u; + } + if (top !== window) { + parent.classFrame.location = pathtoroot + url; + } else { + window.location.href = pathtoroot + url; + } + $("#search").focus(); + } + } + }); +}); diff --git a/docs/acf-paper/src-html/co/aikar/commands/PaperCommandCompletions.html b/docs/acf-paper/src-html/co/aikar/commands/PaperCommandCompletions.html index 402701e8..fe5e3ef6 100644 --- a/docs/acf-paper/src-html/co/aikar/commands/PaperCommandCompletions.html +++ b/docs/acf-paper/src-html/co/aikar/commands/PaperCommandCompletions.html @@ -1,42 +1,43 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026@SuppressWarnings("WeakerAccess")
    -027public class PaperCommandCompletions extends BukkitCommandCompletions {
    -028    public PaperCommandCompletions(PaperCommandManager manager) {
    -029        super(manager);
    -030    }
    -031}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026@SuppressWarnings("WeakerAccess")
    +027public class PaperCommandCompletions extends BukkitCommandCompletions {
    +028    public PaperCommandCompletions(PaperCommandManager manager) {
    +029        super(manager);
    +030    }
    +031}
     
     
     
    @@ -99,5 +100,6 @@
     
     
    +
    diff --git a/docs/acf-paper/src-html/co/aikar/commands/PaperCommandContexts.html b/docs/acf-paper/src-html/co/aikar/commands/PaperCommandContexts.html index ed64ef26..5bee93b1 100644 --- a/docs/acf-paper/src-html/co/aikar/commands/PaperCommandContexts.html +++ b/docs/acf-paper/src-html/co/aikar/commands/PaperCommandContexts.html @@ -1,42 +1,43 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026@SuppressWarnings("WeakerAccess")
    -027public class PaperCommandContexts extends BukkitCommandContexts {
    -028    public PaperCommandContexts(PaperCommandManager manager) {
    -029        super(manager);
    -030    }
    -031}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026@SuppressWarnings("WeakerAccess")
    +027public class PaperCommandContexts extends BukkitCommandContexts {
    +028    public PaperCommandContexts(PaperCommandManager manager) {
    +029        super(manager);
    +030    }
    +031}
     
     
     
    @@ -99,5 +100,6 @@
     
     
    +
    diff --git a/docs/acf-paper/src-html/co/aikar/commands/PaperCommandManager.html b/docs/acf-paper/src-html/co/aikar/commands/PaperCommandManager.html index 7a806c05..fba1e484 100644 --- a/docs/acf-paper/src-html/co/aikar/commands/PaperCommandManager.html +++ b/docs/acf-paper/src-html/co/aikar/commands/PaperCommandManager.html @@ -1,68 +1,69 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.bukkit.plugin.Plugin;
    -027
    -028@SuppressWarnings("WeakerAccess")
    -029public class PaperCommandManager extends BukkitCommandManager {
    -030
    -031    // If we get anything Paper specific
    -032    public PaperCommandManager(Plugin plugin) {
    -033        super(plugin);
    -034        try {
    -035            Class.forName("com.destroystokyo.paper.event.server.AsyncTabCompleteEvent");
    -036            plugin.getServer().getPluginManager().registerEvents(new PaperAsyncTabCompleteHandler(this), plugin);
    -037        } catch (ClassNotFoundException ignored) {
    -038            // Ignored
    -039        }
    -040    }
    -041
    -042    @Override
    -043    public synchronized CommandContexts<BukkitCommandExecutionContext> getCommandContexts() {
    -044        if (this.contexts == null) {
    -045            this.contexts = new PaperCommandContexts(this);
    -046        }
    -047        return this.contexts;
    -048    }
    -049
    -050    @Override
    -051    public synchronized CommandCompletions<BukkitCommandCompletionContext> getCommandCompletions() {
    -052        if (this.completions == null) {
    -053            this.completions = new PaperCommandCompletions(this);
    -054        }
    -055        return this.completions;
    -056    }
    -057}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.bukkit.plugin.Plugin;
    +027
    +028@SuppressWarnings("WeakerAccess")
    +029public class PaperCommandManager extends BukkitCommandManager {
    +030
    +031    // If we get anything Paper specific
    +032    public PaperCommandManager(Plugin plugin) {
    +033        super(plugin);
    +034        try {
    +035            Class.forName("com.destroystokyo.paper.event.server.AsyncTabCompleteEvent");
    +036            plugin.getServer().getPluginManager().registerEvents(new PaperAsyncTabCompleteHandler(this), plugin);
    +037        } catch (ClassNotFoundException ignored) {
    +038            // Ignored
    +039        }
    +040    }
    +041
    +042    @Override
    +043    public synchronized CommandContexts<BukkitCommandExecutionContext> getCommandContexts() {
    +044        if (this.contexts == null) {
    +045            this.contexts = new PaperCommandContexts(this);
    +046        }
    +047        return this.contexts;
    +048    }
    +049
    +050    @Override
    +051    public synchronized CommandCompletions<BukkitCommandCompletionContext> getCommandCompletions() {
    +052        if (this.completions == null) {
    +053            this.completions = new PaperCommandCompletions(this);
    +054        }
    +055        return this.completions;
    +056    }
    +057}
     
     
     
    @@ -125,5 +126,6 @@
     
     
    +
    diff --git a/docs/acf-paper/stylesheet.css b/docs/acf-paper/stylesheet.css index 98055b22..fa246765 100644 --- a/docs/acf-paper/stylesheet.css +++ b/docs/acf-paper/stylesheet.css @@ -1,35 +1,51 @@ -/* Javadoc style sheet */ -/* -Overall document style -*/ +/* + * Javadoc style sheet + */ @import url('resources/fonts/dejavu.css'); +/* + * Styles for individual HTML elements. + * + * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular + * HTML element throughout the page. + */ + body { background-color:#ffffff; color:#353833; font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; font-size:14px; margin:0; + padding:0; + height:100%; + width:100%; +} +iframe { + margin:0; + padding:0; + height:100%; + width:100%; + overflow-y:scroll; + border:none; } a:link, a:visited { text-decoration:none; color:#4A6782; } -a:hover, a:focus { +a[href]:hover, a[href]:focus { text-decoration:none; color:#bb7a2a; } -a:active { - text-decoration:none; - color:#4A6782; -} a[name] { color:#353833; } -a[name]:hover { - text-decoration:none; - color:#353833; +a[name]:before, a[name]:target, a[id]:before, a[id]:target { + content:""; + display:inline-block; + position:relative; + padding-top:129px; + margin-top:-129px; } pre { font-family:'DejaVu Sans Mono', monospace; @@ -78,9 +94,16 @@ table tr td dt code { sup { font-size:8px; } + /* -Document title and Copyright styles -*/ + * Styles for HTML generated by javadoc. + * + * These are style classes that are used by the standard doclet to generate HTML documentation. + */ + +/* + * Styles for document title and copyright. + */ .clear { clear:both; height:0px; @@ -111,8 +134,8 @@ Document title and Copyright styles font-weight:bold; } /* -Navigation bar styles -*/ + * Styles for navigation bar. + */ .bar { background-color:#4D7A97; color:#FFFFFF; @@ -121,6 +144,15 @@ Navigation bar styles font-size:11px; margin:0; } +.navPadding { + padding-top: 107px; +} +.fixedNav { + position:fixed; + width:100%; + z-index:999; + background-color:#ffffff; +} .topNav { background-color:#4D7A97; color:#FFFFFF; @@ -170,7 +202,22 @@ ul.navList li{ padding: 5px 6px; text-transform:uppercase; } -ul.subNavList li{ +ul.navListSearch { + float:right; + margin:0 0 0 0; + padding:0; +} +ul.navListSearch li { + list-style:none; + float:right; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch li label { + position:relative; + right:-16px; +} +ul.subNavList li { list-style:none; float:left; } @@ -196,21 +243,29 @@ ul.subNavList li{ overflow:hidden; } /* -Page header and footer styles -*/ + * Styles for page header and footer. + */ .header, .footer { clear:both; margin:0 20px; padding:5px 0 0 0; } -.indexHeader { - margin:10px; +.indexNav { position:relative; + font-size:12px; + background-color:#dee3e9; } -.indexHeader span{ - margin-right:15px; +.indexNav ul { + margin-top:0; + padding:5px; } -.indexHeader h1 { +.indexNav ul li { + display:inline; + list-style-type:none; + padding-right:10px; + text-transform:uppercase; +} +.indexNav h1 { font-size:13px; } .title { @@ -232,8 +287,8 @@ Page header and footer styles font-size:13px; } /* -Heading styles -*/ + * Styles for headings. + */ div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { background-color:#dee3e9; border:1px solid #d0d9e0; @@ -254,9 +309,10 @@ ul.blockList li.blockList h2 { padding:0px 0 20px 0; } /* -Page layout container styles -*/ -.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + * Styles for page layout containers. + */ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer, +.allClassesContainer, .allPackagesContainer { clear:both; padding:10px 20px; position:relative; @@ -287,7 +343,7 @@ Page layout container styles .contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { margin:5px 0 10px 0px; font-size:14px; - font-family:'DejaVu Sans Mono',monospace; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } .serializedFormContainer dl.nameValue dt { margin-left:1px; @@ -301,8 +357,11 @@ Page layout container styles display:inline; } /* -List styles -*/ + * Styles for lists. + */ +li.circle { + list-style:circle; +} ul.horizontal li { display:inline; font-size:0.9em; @@ -355,19 +414,22 @@ table tr td dl, table tr td dl dt, table tr td dl dd { margin-bottom:1px; } /* -Table styles -*/ -.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + * Styles for tables. + */ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary, +.requiresSummary, .packagesSummary, .providesSummary, .usesSummary { width:100%; + border-spacing:0; border-left:1px solid #EEE; border-right:1px solid #EEE; border-bottom:1px solid #EEE; } -.overviewSummary, .memberSummary { +.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary { padding:0px; } .overviewSummary caption, .memberSummary caption, .typeSummary caption, -.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption, +.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption { position:relative; text-align:left; background-repeat:no-repeat; @@ -382,17 +444,31 @@ Table styles white-space:pre; } .overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, -.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.constantsSummary caption a:link, .deprecatedSummary caption a:link, +.requiresSummary caption a:link, .packagesSummary caption a:link, .providesSummary caption a:link, +.usesSummary caption a:link, .overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, -.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.requiresSummary caption a:hover, .packagesSummary caption a:hover, .providesSummary caption a:hover, +.usesSummary caption a:hover, .overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, -.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.constantsSummary caption a:active, .deprecatedSummary caption a:active, +.requiresSummary caption a:active, .packagesSummary caption a:active, .providesSummary caption a:active, +.usesSummary caption a:active, .overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, -.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { +.constantsSummary caption a:visited, .deprecatedSummary caption a:visited, +.requiresSummary caption a:visited, .packagesSummary caption a:visited, .providesSummary caption a:visited, +.usesSummary caption a:visited { color:#FFFFFF; } +.useSummary caption a:link, .useSummary caption a:hover, .useSummary caption a:active, +.useSummary caption a:visited { + color:#1f389c; +} .overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, -.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span, +.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span, +.usesSummary caption span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -404,7 +480,8 @@ Table styles border: none; height:16px; } -.memberSummary caption span.activeTableTab span { +.memberSummary caption span.activeTableTab span, .packagesSummary caption span.activeTableTab span, +.overviewSummary caption span.activeTableTab span, .typeSummary caption span.activeTableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -415,7 +492,8 @@ Table styles background-color:#F8981D; height:16px; } -.memberSummary caption span.tableTab span { +.memberSummary caption span.tableTab span, .packagesSummary caption span.tableTab span, +.overviewSummary caption span.tableTab span, .typeSummary caption span.tableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -426,7 +504,10 @@ Table styles background-color:#4D7A97; height:16px; } -.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab, +.packagesSummary caption span.tableTab, .packagesSummary caption span.activeTableTab, +.overviewSummary caption span.tableTab, .overviewSummary caption span.activeTableTab, +.typeSummary caption span.tableTab, .typeSummary caption span.activeTableTab { padding-top:0px; padding-left:0px; padding-right:0px; @@ -435,14 +516,16 @@ Table styles display:inline; } .overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, -.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd, +.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd { display:none; width:5px; position:relative; float:left; background-color:#F8981D; } -.memberSummary .activeTableTab .tabEnd { +.memberSummary .activeTableTab .tabEnd, .packagesSummary .activeTableTab .tabEnd, +.overviewSummary .activeTableTab .tabEnd, .typeSummary .activeTableTab .tabEnd { display:none; width:5px; margin-right:3px; @@ -450,66 +533,88 @@ Table styles float:left; background-color:#F8981D; } -.memberSummary .tableTab .tabEnd { +.memberSummary .tableTab .tabEnd, .packagesSummary .tableTab .tabEnd, +.overviewSummary .tableTab .tabEnd, .typeSummary .tableTab .tabEnd { display:none; width:5px; margin-right:3px; position:relative; background-color:#4D7A97; float:left; - +} +.rowColor th, .altColor th { + font-weight:normal; } .overviewSummary td, .memberSummary td, .typeSummary td, -.useSummary td, .constantsSummary td, .deprecatedSummary td { +.useSummary td, .constantsSummary td, .deprecatedSummary td, +.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td { text-align:left; padding:0px 0px 12px 10px; } -th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, -td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .useSummary th, +.constantsSummary th, .packagesSummary th, td.colFirst, td.colSecond, td.colLast, .useSummary td, +.constantsSummary td { vertical-align:top; padding-right:0px; padding-top:8px; padding-bottom:3px; } -th.colFirst, th.colLast, th.colOne, .constantsSummary th { +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .constantsSummary th, +.packagesSummary th { background:#dee3e9; text-align:left; padding:8px 3px 3px 7px; } td.colFirst, th.colFirst { - white-space:nowrap; font-size:13px; } -td.colLast, th.colLast { +td.colSecond, th.colSecond, td.colLast, th.colConstructorName, th.colDeprecatedItemName, th.colLast { font-size:13px; } -td.colOne, th.colOne { +.constantsSummary th, .packagesSummary th { + font-size:13px; +} +.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst, +.providesSummary td.colLast { + white-space:normal; font-size:13px; } .overviewSummary td.colFirst, .overviewSummary th.colFirst, -.useSummary td.colFirst, .useSummary th.colFirst, -.overviewSummary td.colOne, .overviewSummary th.colOne, +.requiresSummary td.colFirst, .requiresSummary th.colFirst, +.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th, +.usesSummary td.colFirst, .usesSummary th.colFirst, +.providesSummary td.colFirst, .providesSummary th.colFirst, .memberSummary td.colFirst, .memberSummary th.colFirst, -.memberSummary td.colOne, .memberSummary th.colOne, -.typeSummary td.colFirst{ - width:25%; +.memberSummary td.colSecond, .memberSummary th.colSecond, .memberSummary th.colConstructorName, +.typeSummary td.colFirst, .typeSummary th.colFirst { vertical-align:top; } -td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { +.packagesSummary th.colLast, .packagesSummary td.colLast { + white-space:normal; +} +td.colFirst a:link, td.colFirst a:visited, +td.colSecond a:link, td.colSecond a:visited, +th.colFirst a:link, th.colFirst a:visited, +th.colSecond a:link, th.colSecond a:visited, +th.colConstructorName a:link, th.colConstructorName a:visited, +th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited, +.constantValuesContainer td a:link, .constantValuesContainer td a:visited, +.allClassesContainer td a:link, .allClassesContainer td a:visited, +.allPackagesContainer td a:link, .allPackagesContainer td a:visited { font-weight:bold; } .tableSubHeadingColor { background-color:#EEEEFF; } -.altColor { +.altColor, .altColor th { background-color:#FFFFFF; } -.rowColor { +.rowColor, .rowColor th { background-color:#EEEEEF; } /* -Content styles -*/ + * Styles for contents. + */ .description pre { margin-top:0; } @@ -520,27 +625,22 @@ Content styles .docSummary { padding:0; } - ul.blockList ul.blockList ul.blockList li.blockList h3 { font-style:normal; } - div.block { font-size:14px; font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } - td.colLast div { padding-top:0px; } - - td.colLast a { padding-bottom:3px; } /* -Formatting effect styles -*/ + * Styles for formatting effect. + */ .sourceLineNo { color:green; padding:0 30px 0 0; @@ -555,20 +655,252 @@ h1.hidden { margin:3px 10px 2px 0px; color:#474747; } -.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { +.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink, +.moduleLabelInPackage, .moduleLabelInType, .overrideSpecifyLabel, .packageLabelInType, +.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, +.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { font-weight:bold; } .deprecationComment, .emphasizedPhrase, .interfaceName { font-style:italic; } - -div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +.deprecationBlock { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +div.block div.deprecationComment, div.block div.block span.emphasizedPhrase, div.block div.block span.interfaceName { font-style:normal; } - -div.contentContainer ul.blockList li.blockList h2{ +div.contentContainer ul.blockList li.blockList h2 { padding-bottom:0px; } +/* + * Styles for IFRAME. + */ +.mainContainer { + margin:0 auto; + padding:0; + height:100%; + width:100%; + position:fixed; + top:0; + left:0; +} +.leftContainer { + height:100%; + position:fixed; + width:320px; +} +.leftTop { + position:relative; + float:left; + width:315px; + top:0; + left:0; + height:30%; + border-right:6px solid #ccc; + border-bottom:6px solid #ccc; +} +.leftBottom { + position:relative; + float:left; + width:315px; + bottom:0; + left:0; + height:70%; + border-right:6px solid #ccc; + border-top:1px solid #000; +} +.rightContainer { + position:absolute; + left:320px; + top:0; + bottom:0; + height:100%; + right:0; + border-left:1px solid #000; +} +.rightIframe { + margin:0; + padding:0; + height:100%; + right:30px; + width:100%; + overflow:visible; + margin-bottom:30px; +} +/* + * Styles specific to HTML5 elements. + */ +main, nav, header, footer, section { + display:block; +} +/* + * Styles for javadoc search. + */ +.ui-autocomplete-category { + font-weight:bold; + font-size:15px; + padding:7px 0 7px 3px; + background-color:#4D7A97; + color:#FFFFFF; +} +.resultItem { + font-size:13px; +} +.ui-autocomplete { + max-height:85%; + max-width:65%; + overflow-y:scroll; + overflow-x:scroll; + white-space:nowrap; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); +} +ul.ui-autocomplete { + position:fixed; + z-index:999999; +} +ul.ui-autocomplete li { + float:left; + clear:both; + width:100%; +} +.resultHighlight { + font-weight:bold; +} +#search { + background-image:url('resources/glass.png'); + background-size:13px; + background-repeat:no-repeat; + background-position:2px 3px; + padding-left:20px; + position:relative; + right:-18px; +} +#reset { + background-color: rgb(255,255,255); + background-image:url('resources/x.png'); + background-position:center; + background-repeat:no-repeat; + background-size:12px; + border:0 none; + width:16px; + height:17px; + position:relative; + left:-4px; + top:-4px; + font-size:0px; +} +.watermark { + color:#545454; +} +.searchTagDescResult { + font-style:italic; + font-size:11px; +} +.searchTagHolderResult { + font-style:italic; + font-size:12px; +} +.searchTagResult:before, .searchTagResult:target { + color:red; +} +.moduleGraph span { + display:none; + position:absolute; +} +.moduleGraph:hover span { + display:block; + margin: -100px 0 0 100px; + z-index: 1; +} +.methodSignature { + white-space:normal; +} + +/* + * Styles for user-provided tables. + * + * borderless: + * No borders, vertical margins, styled caption. + * This style is provided for use with existing doc comments. + * In general, borderless tables should not be used for layout purposes. + * + * plain: + * Plain borders around table and cells, vertical margins, styled caption. + * Best for small tables or for complex tables for tables with cells that span + * rows and columns, when the "striped" style does not work well. + * + * striped: + * Borders around the table and vertical borders between cells, striped rows, + * vertical margins, styled caption. + * Best for tables that have a header row, and a body containing a series of simple rows. + */ + +table.borderless, +table.plain, +table.striped { + margin-top: 10px; + margin-bottom: 10px; +} +table.borderless > caption, +table.plain > caption, +table.striped > caption { + font-weight: bold; + font-size: smaller; +} +table.borderless th, table.borderless td, +table.plain th, table.plain td, +table.striped th, table.striped td { + padding: 2px 5px; +} +table.borderless, +table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, +table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { + border: none; +} +table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { + background-color: transparent; +} +table.plain { + border-collapse: collapse; + border: 1px solid black; +} +table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { + background-color: transparent; +} +table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, +table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { + border: 1px solid black; +} +table.striped { + border-collapse: collapse; + border: 1px solid black; +} +table.striped > thead { + background-color: #E3E3E3; +} +table.striped > thead > tr > th, table.striped > thead > tr > td { + border: 1px solid black; +} +table.striped > tbody > tr:nth-child(even) { + background-color: #EEE +} +table.striped > tbody > tr:nth-child(odd) { + background-color: #FFF +} +table.striped > tbody > tr > th, table.striped > tbody > tr > td { + border-left: 1px solid black; + border-right: 1px solid black; +} +table.striped > tbody > tr > th { + font-weight: normal; +} diff --git a/docs/acf-paper/type-search-index.js b/docs/acf-paper/type-search-index.js new file mode 100644 index 00000000..eacce5cd --- /dev/null +++ b/docs/acf-paper/type-search-index.js @@ -0,0 +1 @@ +typeSearchIndex = [{"l":"All Classes","url":"allclasses-index.html"},{"p":"co.aikar.commands","l":"PaperCommandCompletions"},{"p":"co.aikar.commands","l":"PaperCommandContexts"},{"p":"co.aikar.commands","l":"PaperCommandManager"}] \ No newline at end of file diff --git a/docs/acf-paper/type-search-index.zip b/docs/acf-paper/type-search-index.zip new file mode 100644 index 00000000..ae50c4d7 Binary files /dev/null and b/docs/acf-paper/type-search-index.zip differ diff --git a/docs/acf-sponge/allclasses-index.html b/docs/acf-sponge/allclasses-index.html new file mode 100644 index 00000000..fdd95b11 --- /dev/null +++ b/docs/acf-sponge/allclasses-index.html @@ -0,0 +1,239 @@ + + + + + +All Classes (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    All Classes

    +
    + +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + + diff --git a/docs/acf-sponge/allclasses.html b/docs/acf-sponge/allclasses.html new file mode 100644 index 00000000..260c886a --- /dev/null +++ b/docs/acf-sponge/allclasses.html @@ -0,0 +1,45 @@ + + + + + +All Classes (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + +

    All Classes

    +
    + +
    + + diff --git a/docs/acf-sponge/allpackages-index.html b/docs/acf-sponge/allpackages-index.html new file mode 100644 index 00000000..9e6947bc --- /dev/null +++ b/docs/acf-sponge/allpackages-index.html @@ -0,0 +1,173 @@ + + + + + +All Packages (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    All Packages

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + + diff --git a/docs/acf-sponge/co/aikar/commands/ACFSpongeListener.html b/docs/acf-sponge/co/aikar/commands/ACFSpongeListener.html index 4ee6b0ff..cdfbb099 100644 --- a/docs/acf-sponge/co/aikar/commands/ACFSpongeListener.html +++ b/docs/acf-sponge/co/aikar/commands/ACFSpongeListener.html @@ -1,12 +1,21 @@ - + - ACFSpongeListener (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class ACFSpongeListener

    @@ -117,54 +140,63 @@ extends
  • +
    +
    +
    +
  • @@ -172,65 +204,72 @@ extends
  • +
    +
    +
      -
    • +
    • Method Detail

      - +
      • onSettingsChange

        -
        public void onSettingsChange(org.spongepowered.api.event.entity.living.humanoid.player.PlayerChangeClientSettingsEvent changeSettingsEvent,
        +
        public void onSettingsChange​(org.spongepowered.api.event.entity.living.humanoid.player.PlayerChangeClientSettingsEvent changeSettingsEvent,
                                      org.spongepowered.api.entity.living.player.Player targetPlayer)
      - +
      • onDisconnectCleanup

        -
        public void onDisconnectCleanup(org.spongepowered.api.event.network.ClientConnectionEvent.Disconnect disconnectEvent,
        +
        public void onDisconnectCleanup​(org.spongepowered.api.event.network.ClientConnectionEvent.Disconnect disconnectEvent,
                                         org.spongepowered.api.entity.living.player.Player player)
    +
  • + + diff --git a/docs/acf-sponge/co/aikar/commands/ACFSpongeUtil.html b/docs/acf-sponge/co/aikar/commands/ACFSpongeUtil.html index bc116555..9db66eff 100644 --- a/docs/acf-sponge/co/aikar/commands/ACFSpongeUtil.html +++ b/docs/acf-sponge/co/aikar/commands/ACFSpongeUtil.html @@ -1,12 +1,21 @@ - + - ACFSpongeUtil (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class ACFSpongeUtil

    @@ -117,57 +140,67 @@ extends
  • +
    +
    +
    +
  • @@ -175,12 +208,13 @@ extends
  • +
      -
    • +
    • Constructor Detail

      - +
        @@ -191,57 +225,63 @@ extends
          -
        • +
        • Method Detail

          - +
          • findPlayerSmart

            -
            public static org.spongepowered.api.entity.living.player.Player findPlayerSmart(co.aikar.commands.CommandIssuer issuer,
            -                                                                                String search)
            +
            public static org.spongepowered.api.entity.living.player.Player findPlayerSmart​(co.aikar.commands.CommandIssuer issuer,
            +                                                                                String search)
          - +
          • matchPlayer

            -
            public static List<org.spongepowered.api.entity.living.player.Player> matchPlayer(String partialName)
            +
            public static List<org.spongepowered.api.entity.living.player.Player> matchPlayer​(String partialName)
          - +
        +
  • +
    + diff --git a/docs/acf-sponge/co/aikar/commands/MinecraftMessageKeys.html b/docs/acf-sponge/co/aikar/commands/MinecraftMessageKeys.html index c750ac20..a2a38efe 100644 --- a/docs/acf-sponge/co/aikar/commands/MinecraftMessageKeys.html +++ b/docs/acf-sponge/co/aikar/commands/MinecraftMessageKeys.html @@ -1,12 +1,21 @@ - + - MinecraftMessageKeys (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Enum MinecraftMessageKeys

    @@ -217,100 +257,103 @@ the order they are declared. +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeCommandCompletionContext.html b/docs/acf-sponge/co/aikar/commands/SpongeCommandCompletionContext.html index 4654f28f..be65cebd 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeCommandCompletionContext.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeCommandCompletionContext.html @@ -1,12 +1,21 @@ - + - SpongeCommandCompletionContext (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeCommandCompletionContext

    @@ -122,13 +145,14 @@ extends co.aikar.commands.CommandCompletionContext<
  • +
  • @@ -180,46 +210,51 @@ extends co.aikar.commands.CommandCompletionContext<
  • +
      -
    • +
    • Method Detail

      - +
      • getSource

        -
        public org.spongepowered.api.command.CommandSource getSource()
        +
        public org.spongepowered.api.command.CommandSource getSource()
      - +
      • getPlayer

        -
        public org.spongepowered.api.entity.living.player.Player getPlayer()
        +
        public org.spongepowered.api.entity.living.player.Player getPlayer()
    +
  • +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeCommandCompletions.html b/docs/acf-sponge/co/aikar/commands/SpongeCommandCompletions.html index 38974ddd..7c4b85d0 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeCommandCompletions.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeCommandCompletions.html @@ -1,12 +1,21 @@ - + - SpongeCommandCompletions (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeCommandCompletions

    @@ -116,13 +139,14 @@ extends co.aikar.commands.CommandCompletions<
  • +
    +
    +
  • @@ -176,37 +207,42 @@ extends co.aikar.commands.CommandCompletions<
  • +
    +
  • +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeCommandContexts.html b/docs/acf-sponge/co/aikar/commands/SpongeCommandContexts.html index f94a532f..91b540ee 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeCommandContexts.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeCommandContexts.html @@ -1,12 +1,21 @@ - + - SpongeCommandContexts (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeCommandContexts

    @@ -116,13 +139,14 @@ extends co.aikar.commands.CommandContexts<
  • +
    +
    +
  • @@ -176,37 +207,42 @@ extends co.aikar.commands.CommandContexts<
  • +
    +
  • +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeCommandExecutionContext.html b/docs/acf-sponge/co/aikar/commands/SpongeCommandExecutionContext.html index 09c60dd2..519ddd98 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeCommandExecutionContext.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeCommandExecutionContext.html @@ -1,12 +1,21 @@ - + - SpongeCommandExecutionContext (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeCommandExecutionContext

    @@ -122,13 +145,14 @@ extends co.aikar.commands.CommandExecutionContext<
  • +
      -
    • +
    • Field Summary

        -
      • +
      • Fields inherited from class co.aikar.commands.CommandExecutionContext

        @@ -136,43 +160,49 @@ extends co.aikar.commands.CommandExecutionContext<
          -
        • +
        • Method Summary

          - +
          - + + - + + - + +
          All Methods Instance Methods Concrete Methods 
          Modifier and TypeMethod and DescriptionMethodDescription
          org.spongepowered.api.entity.living.player.PlayergetPlayer() getPlayer() 
          org.spongepowered.api.command.CommandSourcegetSource() getSource() 
            -
          • +
          • Methods inherited from class co.aikar.commands.CommandExecutionContext

            canOverridePlayerContext, getAnnotation, getAnnotationValue, getAnnotationValue, getArgs, getBooleanFlagValue, getBooleanFlagValue, getCmd, getDoubleFlagValue, getFirstArg, getFlags, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFloatFlagValue, getIndex, getIntFlagValue, getIssuer, getLastArg, getLongFlagValue, getNumParams, getParam, getParameterPermissions, getPassedArgs, getResolvedArg, getResolvedArg, getResolvedArg, hasAnnotation, hasFlag, isLastArg, isOptional, joinArgs, joinArgs, popFirstArg, popLastArg
        +
  • @@ -180,46 +210,51 @@ extends co.aikar.commands.CommandExecutionContext<
  • +
      -
    • +
    • Method Detail

      - +
      • getSource

        -
        public org.spongepowered.api.command.CommandSource getSource()
        +
        public org.spongepowered.api.command.CommandSource getSource()
      - +
      • getPlayer

        -
        public org.spongepowered.api.entity.living.player.Player getPlayer()
        +
        public org.spongepowered.api.entity.living.player.Player getPlayer()
    +
  • +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeCommandIssuer.html b/docs/acf-sponge/co/aikar/commands/SpongeCommandIssuer.html index a4758c83..1fcd5106 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeCommandIssuer.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeCommandIssuer.html @@ -1,12 +1,21 @@ - + - SpongeCommandIssuer (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeCommandIssuer

    @@ -193,142 +228,147 @@ implements co.aikar.commands.CommandIssuer
    • +
        -
      • +
      • Method Detail

        - +
        • isPlayer

          -
          public boolean isPlayer()
          +
          public boolean isPlayer()
          Specified by:
          isPlayer in interface co.aikar.commands.CommandIssuer
        - +
        • getIssuer

          -
          public org.spongepowered.api.command.CommandSource getIssuer()
          +
          public org.spongepowered.api.command.CommandSource getIssuer()
          Specified by:
          getIssuer in interface co.aikar.commands.CommandIssuer
        - +
        • getUniqueId

          -
          @NotNull
          -public @NotNull UUID getUniqueId()
          +
          @NotNull
          +public @NotNull UUID getUniqueId()
          Specified by:
          getUniqueId in interface co.aikar.commands.CommandIssuer
        - +
        • getPlayer

          -
          public org.spongepowered.api.entity.living.player.Player getPlayer()
          +
          public org.spongepowered.api.entity.living.player.Player getPlayer()
        - +
        • getManager

          -
          public co.aikar.commands.CommandManager getManager()
          +
          public co.aikar.commands.CommandManager getManager()
          Specified by:
          getManager in interface co.aikar.commands.CommandIssuer
        - + - +
        • hasPermission

          -
          public boolean hasPermission(String permission)
          +
          public boolean hasPermission​(String permission)
          Specified by:
          hasPermission in interface co.aikar.commands.CommandIssuer
        - + - +
      +
    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeCommandManager.html b/docs/acf-sponge/co/aikar/commands/SpongeCommandManager.html index 9b4583b0..93812d34 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeCommandManager.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeCommandManager.html @@ -1,12 +1,21 @@ - + - SpongeCommandManager (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeCommandManager

    @@ -122,40 +145,47 @@ extends co.aikar.commands.CommandManager<org.spongepowered.api.command.Comman @@ -299,326 +354,335 @@ extends co.aikar.commands.CommandManager<org.spongepowered.api.command.Comman +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeCommandOperationContext.html b/docs/acf-sponge/co/aikar/commands/SpongeCommandOperationContext.html index a2597328..7a9b79c0 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeCommandOperationContext.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeCommandOperationContext.html @@ -1,12 +1,21 @@ - + - SpongeCommandOperationContext (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeCommandOperationContext

    @@ -165,46 +193,51 @@ extends co.aikar.commands.CommandOperationContext
    • +
        -
      • +
      • Method Detail

        - +
        • getResult

          -
          public org.spongepowered.api.command.CommandResult getResult()
          +
          public org.spongepowered.api.command.CommandResult getResult()
        - +
        • setResult

          -
          public void setResult(org.spongepowered.api.command.CommandResult result)
          +
          public void setResult​(org.spongepowered.api.command.CommandResult result)
      +
    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeConditionContext.html b/docs/acf-sponge/co/aikar/commands/SpongeConditionContext.html index e6cd20de..cee02cac 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeConditionContext.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeConditionContext.html @@ -1,12 +1,21 @@ - + - SpongeConditionContext (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeConditionContext

    @@ -122,42 +145,47 @@ extends co.aikar.commands.ConditionContext<
  • +
    +
  • @@ -165,46 +193,51 @@ extends co.aikar.commands.ConditionContext<
  • +
      -
    • +
    • Method Detail

      - +
      • getSource

        -
        public org.spongepowered.api.command.CommandSource getSource()
        +
        public org.spongepowered.api.command.CommandSource getSource()
      - +
      • getPlayer

        -
        public org.spongepowered.api.entity.living.player.Player getPlayer()
        +
        public org.spongepowered.api.entity.living.player.Player getPlayer()
    +
  • +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeLocales.html b/docs/acf-sponge/co/aikar/commands/SpongeLocales.html index 4f3c4314..69e323d9 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeLocales.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeLocales.html @@ -1,12 +1,21 @@ - + - SpongeLocales (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeLocales

    @@ -193,35 +226,38 @@ extends co.aikar.commands.Locales +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeMessageFormatter.html b/docs/acf-sponge/co/aikar/commands/SpongeMessageFormatter.html index a69d2160..436c70fd 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeMessageFormatter.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeMessageFormatter.html @@ -1,12 +1,21 @@ - + - SpongeMessageFormatter (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeMessageFormatter

    @@ -179,59 +210,62 @@ extends co.aikar.commands.MessageFormatter<org.spongepowered.api.text.format.
    • +
      +
      +
        -
      • +
      • Method Detail

        - +
        • format

          -
          public String format(org.spongepowered.api.text.format.TextColor color,
          -                     String message)
          -
          -
          Specified by:
          -
          format in class co.aikar.commands.MessageFormatter<org.spongepowered.api.text.format.TextColor>
          -
          +
          public String format​(org.spongepowered.api.text.format.TextColor color,
          +                     String message)
      +
    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeRegisteredCommand.html b/docs/acf-sponge/co/aikar/commands/SpongeRegisteredCommand.html index d50e2d38..83bcf9ad 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeRegisteredCommand.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeRegisteredCommand.html @@ -1,12 +1,21 @@ - + - SpongeRegisteredCommand (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeRegisteredCommand

    @@ -122,13 +145,14 @@ extends co.aikar.commands.RegisteredCommand<
  • +
  • @@ -180,54 +210,59 @@ extends co.aikar.commands.RegisteredCommand<
  • +
    +
  • +
    + diff --git a/docs/acf-sponge/co/aikar/commands/SpongeRootCommand.html b/docs/acf-sponge/co/aikar/commands/SpongeRootCommand.html index 2494e695..6b7c5700 100644 --- a/docs/acf-sponge/co/aikar/commands/SpongeRootCommand.html +++ b/docs/acf-sponge/co/aikar/commands/SpongeRootCommand.html @@ -1,12 +1,21 @@ - + - SpongeRootCommand (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class SpongeRootCommand

      -
    • java.lang.Object
    • +
    • java.lang.Object
      • co.aikar.commands.SpongeRootCommand
      • @@ -108,12 +132,11 @@ var activeTableTab = "activeTableTab";
      • All Implemented Interfaces:
        -
        co.aikar.commands.RootCommand, org.spongepowered.api.command.CommandCallable
        +
        co.aikar.commands.RootCommand, org.spongepowered.api.command.CommandCallable

        -
        public class SpongeRootCommand
        -extends Object
        +extends Object
         implements org.spongepowered.api.command.CommandCallable, co.aikar.commands.RootCommand
      @@ -122,78 +145,92 @@ implements org.spongepowered.api.command.CommandCallable, co.aikar.commands.Root
    @@ -208,34 +246,35 @@ implements org.spongepowered.api.command.CommandCallable, co.aikar.commands.Root
    • +
        -
      • +
      • Method Detail

        - + - +
        • process

          -
          public org.spongepowered.api.command.CommandResult process(@NotNull
          +
          public org.spongepowered.api.command.CommandResult process​(@NotNull
                                                                      @NotNull org.spongepowered.api.command.CommandSource source,
                                                                      @NotNull
          -                                                           @NotNull String arguments)
          +                                                           @NotNull String arguments)
                                                               throws org.spongepowered.api.command.CommandException
          Specified by:
          @@ -245,17 +284,17 @@ implements org.spongepowered.api.command.CommandCallable, co.aikar.commands.Root
        - +
        • getSuggestions

          -
          public List<StringgetSuggestions(@NotNull
          +
          public List<StringgetSuggestions​(@NotNull
                                              @NotNull org.spongepowered.api.command.CommandSource source,
                                              @NotNull
          -                                   @NotNull String arguments,
          -                                   @Nullable
          +                                   @NotNull String arguments,
          +                                   @Nullable
                                              org.spongepowered.api.world.Location<org.spongepowered.api.world.World> location)
                                       throws org.spongepowered.api.command.CommandException
          @@ -266,13 +305,13 @@ implements org.spongepowered.api.command.CommandCallable, co.aikar.commands.Root
        - +
        • testPermission

          -
          public boolean testPermission(@NotNull
          +
          public boolean testPermission​(@NotNull
                                         @NotNull org.spongepowered.api.command.CommandSource source)
          Specified by:
          @@ -280,13 +319,13 @@ implements org.spongepowered.api.command.CommandCallable, co.aikar.commands.Root
        - +
        • getShortDescription

          -
          public Optional<org.spongepowered.api.text.Text> getShortDescription(@NotNull
          +
          public Optional<org.spongepowered.api.text.Text> getShortDescription​(@NotNull
                                                                                @NotNull org.spongepowered.api.command.CommandSource source)
          Specified by:
          @@ -294,13 +333,13 @@ implements org.spongepowered.api.command.CommandCallable, co.aikar.commands.Root
        - +
        • getHelp

          -
          public Optional<org.spongepowered.api.text.Text> getHelp(@NotNull
          +
          public Optional<org.spongepowered.api.text.Text> getHelp​(@NotNull
                                                                    @NotNull org.spongepowered.api.command.CommandSource source)
          Specified by:
          @@ -308,13 +347,13 @@ implements org.spongepowered.api.command.CommandCallable, co.aikar.commands.Root
        - +
        • getUsage

          -
          public org.spongepowered.api.text.Text getUsage(@NotNull
          +
          public org.spongepowered.api.text.Text getUsage​(@NotNull
                                                           @NotNull org.spongepowered.api.command.CommandSource source)
          Specified by:
          @@ -322,65 +361,65 @@ implements org.spongepowered.api.command.CommandCallable, co.aikar.commands.Root
        - +
        • addChild

          -
          public void addChild(co.aikar.commands.BaseCommand command)
          +
          public void addChild​(co.aikar.commands.BaseCommand command)
          Specified by:
          addChild in interface co.aikar.commands.RootCommand
        - +
        • getDefCommand

          -
          public co.aikar.commands.BaseCommand getDefCommand()
          +
          public co.aikar.commands.BaseCommand getDefCommand()
          Specified by:
          getDefCommand in interface co.aikar.commands.RootCommand
        - +
        • getManager

          -
          public co.aikar.commands.CommandManager getManager()
          +
          public co.aikar.commands.CommandManager getManager()
          Specified by:
          getManager in interface co.aikar.commands.RootCommand
        - +
        • getSubCommands

          -
          public com.google.common.collect.SetMultimap<String,co.aikar.commands.RegisteredCommand> getSubCommands()
          +
          public com.google.common.collect.SetMultimap<String,​co.aikar.commands.RegisteredCommand> getSubCommands()
          Specified by:
          getSubCommands in interface co.aikar.commands.RootCommand
        - +
        • getChildren

          -
          public List<co.aikar.commands.BaseCommand> getChildren()
          +
          public List<co.aikar.commands.BaseCommand> getChildren()
          Specified by:
          getChildren in interface co.aikar.commands.RootCommand
          @@ -389,21 +428,25 @@ implements org.spongepowered.api.command.CommandCallable, co.aikar.commands.Root
      +
    +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    diff --git a/docs/acf-sponge/co/aikar/commands/class-use/ACFSpongeListener.html b/docs/acf-sponge/co/aikar/commands/class-use/ACFSpongeListener.html index a62dab6b..4f8d6505 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/ACFSpongeListener.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/ACFSpongeListener.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ACFSpongeListener (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.ACFSpongeListener

    No usage of co.aikar.commands.ACFSpongeListener
    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/ACFSpongeUtil.html b/docs/acf-sponge/co/aikar/commands/class-use/ACFSpongeUtil.html index 2f90d1f1..95b02797 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/ACFSpongeUtil.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/ACFSpongeUtil.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ACFSpongeUtil (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.ACFSpongeUtil

    No usage of co.aikar.commands.ACFSpongeUtil
    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/MinecraftMessageKeys.html b/docs/acf-sponge/co/aikar/commands/class-use/MinecraftMessageKeys.html index 345306be..4e28b304 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/MinecraftMessageKeys.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/MinecraftMessageKeys.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.MinecraftMessageKeys (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.MinecraftMessageKeys

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandCompletionContext.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandCompletionContext.html index 86a40051..6fed478d 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandCompletionContext.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandCompletionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeCommandCompletionContext (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeCommandCompletionContext

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandCompletions.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandCompletions.html index d6b44027..80b28625 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandCompletions.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandCompletions.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeCommandCompletions (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeCommandCompletions

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandContexts.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandContexts.html index fdfb2dcf..0cebb319 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandContexts.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandContexts.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeCommandContexts (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeCommandContexts

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandExecutionContext.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandExecutionContext.html index 09d491c0..6ba8ab6c 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandExecutionContext.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandExecutionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeCommandExecutionContext (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeCommandExecutionContext

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandIssuer.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandIssuer.html index 4789fb89..dc6c697c 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandIssuer.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandIssuer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeCommandIssuer (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeCommandIssuer

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandManager.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandManager.html index 76066f15..29b1789c 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandManager.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandManager.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeCommandManager (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeCommandManager

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandOperationContext.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandOperationContext.html index 8dc7a3dc..b12fcbee 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandOperationContext.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeCommandOperationContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeCommandOperationContext (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeCommandOperationContext

    No usage of co.aikar.commands.SpongeCommandOperationContext
    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeConditionContext.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeConditionContext.html index ce6bbec5..4147052a 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeConditionContext.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeConditionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeConditionContext (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeConditionContext

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeLocales.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeLocales.html index 31d0fe26..ed49a145 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeLocales.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeLocales.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeLocales (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeLocales

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeMessageFormatter.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeMessageFormatter.html index a93193a0..8bdcec2d 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeMessageFormatter.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeMessageFormatter.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeMessageFormatter (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeMessageFormatter

    No usage of co.aikar.commands.SpongeMessageFormatter
    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeRegisteredCommand.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeRegisteredCommand.html index bd3343ec..ce075341 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeRegisteredCommand.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeRegisteredCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeRegisteredCommand (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeRegisteredCommand

    No usage of co.aikar.commands.SpongeRegisteredCommand
    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/class-use/SpongeRootCommand.html b/docs/acf-sponge/co/aikar/commands/class-use/SpongeRootCommand.html index 7cbdd0a1..2d31682a 100644 --- a/docs/acf-sponge/co/aikar/commands/class-use/SpongeRootCommand.html +++ b/docs/acf-sponge/co/aikar/commands/class-use/SpongeRootCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.SpongeRootCommand (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.SpongeRootCommand

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/contexts/CommandResultSupplier.html b/docs/acf-sponge/co/aikar/commands/contexts/CommandResultSupplier.html index 1e022443..9c39c113 100644 --- a/docs/acf-sponge/co/aikar/commands/contexts/CommandResultSupplier.html +++ b/docs/acf-sponge/co/aikar/commands/contexts/CommandResultSupplier.html @@ -1,12 +1,21 @@ - + - CommandResultSupplier (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands.contexts
    +

    Class CommandResultSupplier

      -
    • java.lang.Object
    • +
    • java.lang.Object
      • co.aikar.commands.contexts.CommandResultSupplier
      • @@ -108,13 +132,12 @@ var activeTableTab = "activeTableTab";
      • All Implemented Interfaces:
        -
        Consumer<org.spongepowered.api.command.CommandResult>
        +
        Consumer<org.spongepowered.api.command.CommandResult>

        -
        public class CommandResultSupplier
        -extends Object
        -implements Consumer<org.spongepowered.api.command.CommandResult>
        +extends Object +implements Consumer<org.spongepowered.api.command.CommandResult>
    @@ -122,55 +145,63 @@ implements
  • +
    +
    +
    +
  • @@ -178,12 +209,13 @@ implements
  • +
      -
    • +
    • Constructor Detail

      - +
        @@ -194,42 +226,48 @@ implements
          -
        • +
        • Method Detail

          - +
          • accept

            -
            public void accept(org.spongepowered.api.command.CommandResult commandResult)
            +
            public void accept​(org.spongepowered.api.command.CommandResult commandResult)
            Specified by:
            -
            accept in interface Consumer<org.spongepowered.api.command.CommandResult>
            +
            accept in interface Consumer<org.spongepowered.api.command.CommandResult>
        +
  • +
    + diff --git a/docs/acf-sponge/co/aikar/commands/contexts/OnlinePlayer.html b/docs/acf-sponge/co/aikar/commands/contexts/OnlinePlayer.html index b51535c5..c25b05a2 100644 --- a/docs/acf-sponge/co/aikar/commands/contexts/OnlinePlayer.html +++ b/docs/acf-sponge/co/aikar/commands/contexts/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - OnlinePlayer (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands.contexts
    +

    Class OnlinePlayer

    @@ -120,61 +143,69 @@ extends
  • +
    +
    +
      -
    • +
    • Constructor Summary

      - +
      - + + - +
      Constructors 
      Constructor and DescriptionConstructorDescription
      OnlinePlayer(org.spongepowered.api.entity.living.player.Player player) -
      Deprecated. 
      +
      OnlinePlayer​(org.spongepowered.api.entity.living.player.Player player) +
      Deprecated.
       
    +
    +
    +
  • @@ -182,38 +213,43 @@ extends
  • +
      -
    • +
    • Constructor Detail

      - +
      • OnlinePlayer

        -
        public OnlinePlayer(org.spongepowered.api.entity.living.player.Player player)
        -
        Deprecated. 
        +
        public OnlinePlayer​(org.spongepowered.api.entity.living.player.Player player)
        +
        Deprecated.
    +
  • +
    + diff --git a/docs/acf-sponge/co/aikar/commands/contexts/class-use/CommandResultSupplier.html b/docs/acf-sponge/co/aikar/commands/contexts/class-use/CommandResultSupplier.html index 7db4cc2a..532e7611 100644 --- a/docs/acf-sponge/co/aikar/commands/contexts/class-use/CommandResultSupplier.html +++ b/docs/acf-sponge/co/aikar/commands/contexts/class-use/CommandResultSupplier.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.contexts.CommandResultSupplier (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.contexts.CommandResultSupplier

    No usage of co.aikar.commands.contexts.CommandResultSupplier
    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/contexts/class-use/OnlinePlayer.html b/docs/acf-sponge/co/aikar/commands/contexts/class-use/OnlinePlayer.html index 3a2f13a4..69ec8936 100644 --- a/docs/acf-sponge/co/aikar/commands/contexts/class-use/OnlinePlayer.html +++ b/docs/acf-sponge/co/aikar/commands/contexts/class-use/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.contexts.OnlinePlayer (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.contexts.OnlinePlayer

    No usage of co.aikar.commands.contexts.OnlinePlayer
    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/contexts/package-summary.html b/docs/acf-sponge/co/aikar/commands/contexts/package-summary.html index cd10eee5..975b6da9 100644 --- a/docs/acf-sponge/co/aikar/commands/contexts/package-summary.html +++ b/docs/acf-sponge/co/aikar/commands/contexts/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.contexts (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Package co.aikar.commands.contexts

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/sponge/contexts/OnlinePlayer.html b/docs/acf-sponge/co/aikar/commands/sponge/contexts/OnlinePlayer.html index e281fdca..860d2430 100644 --- a/docs/acf-sponge/co/aikar/commands/sponge/contexts/OnlinePlayer.html +++ b/docs/acf-sponge/co/aikar/commands/sponge/contexts/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - OnlinePlayer (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands.sponge.contexts
    +

    Class OnlinePlayer

    @@ -121,79 +144,94 @@ extends
  • +
      -
    • +
    • Field Summary

      - +
      - + + - + +
      Fields 
      Modifier and TypeField and DescriptionFieldDescription
      org.spongepowered.api.entity.living.player.Playerplayer player 
    +
    +
      -
    • +
    • Constructor Summary

      - +
      - + + - + +
      Constructors 
      Constructor and DescriptionConstructorDescription
      OnlinePlayer(org.spongepowered.api.entity.living.player.Player player) OnlinePlayer​(org.spongepowered.api.entity.living.player.Player player) 
    +
    +
    +
  • @@ -201,12 +239,13 @@ extends
  • +
      -
    • +
    • Field Detail

      - +
        @@ -217,94 +256,102 @@ extends
          -
        • +
        • Constructor Detail

          - +
          • OnlinePlayer

            -
            public OnlinePlayer(org.spongepowered.api.entity.living.player.Player player)
            +
            public OnlinePlayer​(org.spongepowered.api.entity.living.player.Player player)
        +
    +
    +
  • +
    + diff --git a/docs/acf-sponge/co/aikar/commands/sponge/contexts/class-use/OnlinePlayer.html b/docs/acf-sponge/co/aikar/commands/sponge/contexts/class-use/OnlinePlayer.html index 010bd4c7..b7b593df 100644 --- a/docs/acf-sponge/co/aikar/commands/sponge/contexts/class-use/OnlinePlayer.html +++ b/docs/acf-sponge/co/aikar/commands/sponge/contexts/class-use/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.sponge.contexts.OnlinePlayer (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.sponge.contexts.OnlinePlayer

    +
    + diff --git a/docs/acf-sponge/co/aikar/commands/sponge/contexts/package-summary.html b/docs/acf-sponge/co/aikar/commands/sponge/contexts/package-summary.html index b6d9a553..f53acf65 100644 --- a/docs/acf-sponge/co/aikar/commands/sponge/contexts/package-summary.html +++ b/docs/acf-sponge/co/aikar/commands/sponge/contexts/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.sponge.contexts (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Package co.aikar.commands.sponge.contexts

    +
    + diff --git a/docs/acf-sponge/constant-values.html b/docs/acf-sponge/constant-values.html index c3bb5d1d..6b49b143 100644 --- a/docs/acf-sponge/constant-values.html +++ b/docs/acf-sponge/constant-values.html @@ -1,12 +1,21 @@ - + - Constant Field Values (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Constant Field Values

    +

    Contents

    +
    +
    + diff --git a/docs/acf-sponge/deprecated-list.html b/docs/acf-sponge/deprecated-list.html index cafcf456..65423ba4 100644 --- a/docs/acf-sponge/deprecated-list.html +++ b/docs/acf-sponge/deprecated-list.html @@ -1,12 +1,21 @@ - + - Deprecated List (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Deprecated API

    Contents

    -
    +
    +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + diff --git a/docs/acf-sponge/jquery/external/jquery/jquery.js b/docs/acf-sponge/jquery/external/jquery/jquery.js new file mode 100644 index 00000000..9b5206bc --- /dev/null +++ b/docs/acf-sponge/jquery/external/jquery/jquery.js @@ -0,0 +1,10364 @@ +/*! + * jQuery JavaScript Library v3.3.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2018-01-20T17:24Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + + + + var preservedScriptAttributes = { + type: true, + src: true, + noModule: true + }; + + function DOMEval( code, doc, node ) { + doc = doc || document; + + var i, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + if ( node[ i ] ) { + script[ i ] = node[ i ]; + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.3.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && Array.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( nodeName( elem, "iframe" ) ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
    " ], + col: [ 2, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + div.style.position = "absolute"; + scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a property mapped along what jQuery.cssProps suggests or to +// a vendor prefixed property. +function finalPropName( name ) { + var ret = jQuery.cssProps[ name ]; + if ( !ret ) { + ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + } + return ret; +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + ) ); + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + val = curCSS( elem, dimension, styles ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox; + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = valueIsBorderBox && + ( support.boxSizingReliable() || val === elem.style[ dimension ] ); + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + if ( val === "auto" || + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { + + val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; + + // offsetWidth/offsetHeight provide border-box values + valueIsBorderBox = true; + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra && boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ); + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && support.scrollboxSize() === styles.position ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = Date.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "\r\n"; + +// inject VBScript +document.write(IEBinaryToArray_ByteStr_Script); + +global.JSZipUtils._getBinaryFromXHR = function (xhr) { + var binary = xhr.responseBody; + var byteMapping = {}; + for ( var i = 0; i < 256; i++ ) { + for ( var j = 0; j < 256; j++ ) { + byteMapping[ String.fromCharCode( i + (j << 8) ) ] = + String.fromCharCode(i) + String.fromCharCode(j); + } + } + var rawBytes = IEBinaryToArray_ByteStr(binary); + var lastChr = IEBinaryToArray_ByteStr_Last(binary); + return rawBytes.replace(/[\s\S]/g, function( match ) { + return byteMapping[match]; + }) + lastChr; +}; + +// enforcing Stuk's coding style +// vim: set shiftwidth=4 softtabstop=4: + +},{}]},{},[1]) +; diff --git a/docs/acf-sponge/jquery/jszip-utils/dist/jszip-utils-ie.min.js b/docs/acf-sponge/jquery/jszip-utils/dist/jszip-utils-ie.min.js new file mode 100644 index 00000000..93d8bc8e --- /dev/null +++ b/docs/acf-sponge/jquery/jszip-utils/dist/jszip-utils-ie.min.js @@ -0,0 +1,10 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); diff --git a/docs/acf-sponge/jquery/jszip-utils/dist/jszip-utils.js b/docs/acf-sponge/jquery/jszip-utils/dist/jszip-utils.js new file mode 100644 index 00000000..775895ec --- /dev/null +++ b/docs/acf-sponge/jquery/jszip-utils/dist/jszip-utils.js @@ -0,0 +1,118 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ + +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64; + enc4 = remainingBytes > 2 ? (chr3 & 63) : 64; + + output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4)); + + } + + return output.join(""); +}; + +// public method for decoding +exports.decode = function(input) { + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0, resultIndex = 0; + + var dataUrlPrefix = "data:"; + + if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) { + // This is a common error: people give a data url + // (data:image/png;base64,iVBOR...) with a {base64: true} and + // wonders why things don't work. + // We can detect that the string input looks like a data url but we + // *can't* be sure it is one: removing everything up to the comma would + // be too dangerous. + throw new Error("Invalid base64 input, it looks like a data url."); + } + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + var totalLength = input.length * 3 / 4; + if(input.charAt(input.length - 1) === _keyStr.charAt(64)) { + totalLength--; + } + if(input.charAt(input.length - 2) === _keyStr.charAt(64)) { + totalLength--; + } + if (totalLength % 1 !== 0) { + // totalLength is not an integer, the length does not match a valid + // base64 content. That can happen if: + // - the input is not a base64 content + // - the input is *almost* a base64 content, with a extra chars at the + // beginning or at the end + // - the input uses a base64 variant (base64url for example) + throw new Error("Invalid base64 input, bad content length."); + } + var output; + if (support.uint8array) { + output = new Uint8Array(totalLength|0); + } else { + output = new Array(totalLength|0); + } + + while (i < input.length) { + + enc1 = _keyStr.indexOf(input.charAt(i++)); + enc2 = _keyStr.indexOf(input.charAt(i++)); + enc3 = _keyStr.indexOf(input.charAt(i++)); + enc4 = _keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output[resultIndex++] = chr1; + + if (enc3 !== 64) { + output[resultIndex++] = chr2; + } + if (enc4 !== 64) { + output[resultIndex++] = chr3; + } + + } + + return output; +}; + +},{"./support":30,"./utils":32}],2:[function(require,module,exports){ +'use strict'; + +var external = require("./external"); +var DataWorker = require('./stream/DataWorker'); +var DataLengthProbe = require('./stream/DataLengthProbe'); +var Crc32Probe = require('./stream/Crc32Probe'); +var DataLengthProbe = require('./stream/DataLengthProbe'); + +/** + * Represent a compressed object, with everything needed to decompress it. + * @constructor + * @param {number} compressedSize the size of the data compressed. + * @param {number} uncompressedSize the size of the data after decompression. + * @param {number} crc32 the crc32 of the decompressed file. + * @param {object} compression the type of compression, see lib/compressions.js. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data. + */ +function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) { + this.compressedSize = compressedSize; + this.uncompressedSize = uncompressedSize; + this.crc32 = crc32; + this.compression = compression; + this.compressedContent = data; +} + +CompressedObject.prototype = { + /** + * Create a worker to get the uncompressed content. + * @return {GenericWorker} the worker. + */ + getContentWorker : function () { + var worker = new DataWorker(external.Promise.resolve(this.compressedContent)) + .pipe(this.compression.uncompressWorker()) + .pipe(new DataLengthProbe("data_length")); + + var that = this; + worker.on("end", function () { + if(this.streamInfo['data_length'] !== that.uncompressedSize) { + throw new Error("Bug : uncompressed data size mismatch"); + } + }); + return worker; + }, + /** + * Create a worker to get the compressed content. + * @return {GenericWorker} the worker. + */ + getCompressedWorker : function () { + return new DataWorker(external.Promise.resolve(this.compressedContent)) + .withStreamInfo("compressedSize", this.compressedSize) + .withStreamInfo("uncompressedSize", this.uncompressedSize) + .withStreamInfo("crc32", this.crc32) + .withStreamInfo("compression", this.compression) + ; + } +}; + +/** + * Chain the given worker with other workers to compress the content with the + * given compresion. + * @param {GenericWorker} uncompressedWorker the worker to pipe. + * @param {Object} compression the compression object. + * @param {Object} compressionOptions the options to use when compressing. + * @return {GenericWorker} the new worker compressing the content. + */ +CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions) { + return uncompressedWorker + .pipe(new Crc32Probe()) + .pipe(new DataLengthProbe("uncompressedSize")) + .pipe(compression.compressWorker(compressionOptions)) + .pipe(new DataLengthProbe("compressedSize")) + .withStreamInfo("compression", compression); +}; + +module.exports = CompressedObject; + +},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require("./stream/GenericWorker"); + +exports.STORE = { + magic: "\x00\x00", + compressWorker : function (compressionOptions) { + return new GenericWorker("STORE compression"); + }, + uncompressWorker : function () { + return new GenericWorker("STORE decompression"); + } +}; +exports.DEFLATE = require('./flate'); + +},{"./flate":7,"./stream/GenericWorker":28}],4:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); + +/** + * The following functions come from pako, from pako/lib/zlib/crc32.js + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +// That's all for the pako functions. + +/** + * Compute the crc32 of a string. + * This is almost the same as the function crc32, but for strings. Using the + * same function for the two use cases leads to horrible performances. + * @param {Number} crc the starting value of the crc. + * @param {String} str the string to use. + * @param {Number} len the length of the string. + * @param {Number} pos the starting position for the crc32 computation. + * @return {Number} the computed crc32. + */ +function crc32str(crc, str, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +module.exports = function crc32wrapper(input, crc) { + if (typeof input === "undefined" || !input.length) { + return 0; + } + + var isArray = utils.getTypeOf(input) !== "string"; + + if(isArray) { + return crc32(crc|0, input, input.length, 0); + } else { + return crc32str(crc|0, input, input.length, 0); + } +}; + +},{"./utils":32}],5:[function(require,module,exports){ +'use strict'; +exports.base64 = false; +exports.binary = false; +exports.dir = false; +exports.createFolders = true; +exports.date = null; +exports.compression = null; +exports.compressionOptions = null; +exports.comment = null; +exports.unixPermissions = null; +exports.dosPermissions = null; + +},{}],6:[function(require,module,exports){ +/* global Promise */ +'use strict'; + +// load the global object first: +// - it should be better integrated in the system (unhandledRejection in node) +// - the environment may have a custom Promise implementation (see zone.js) +var ES6Promise = null; +if (typeof Promise !== "undefined") { + ES6Promise = Promise; +} else { + ES6Promise = require("lie"); +} + +/** + * Let the user use/change some implementations. + */ +module.exports = { + Promise: ES6Promise +}; + +},{"lie":58}],7:[function(require,module,exports){ +'use strict'; +var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); + +var pako = require("pako"); +var utils = require("./utils"); +var GenericWorker = require("./stream/GenericWorker"); + +var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array"; + +exports.magic = "\x08\x00"; + +/** + * Create a worker that uses pako to inflate/deflate. + * @constructor + * @param {String} action the name of the pako function to call : either "Deflate" or "Inflate". + * @param {Object} options the options to use when (de)compressing. + */ +function FlateWorker(action, options) { + GenericWorker.call(this, "FlateWorker/" + action); + + this._pako = null; + this._pakoAction = action; + this._pakoOptions = options; + // the `meta` object from the last chunk received + // this allow this worker to pass around metadata + this.meta = {}; +} + +utils.inherits(FlateWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +FlateWorker.prototype.processChunk = function (chunk) { + this.meta = chunk.meta; + if (this._pako === null) { + this._createPako(); + } + this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false); +}; + +/** + * @see GenericWorker.flush + */ +FlateWorker.prototype.flush = function () { + GenericWorker.prototype.flush.call(this); + if (this._pako === null) { + this._createPako(); + } + this._pako.push([], true); +}; +/** + * @see GenericWorker.cleanUp + */ +FlateWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this._pako = null; +}; + +/** + * Create the _pako object. + * TODO: lazy-loading this object isn't the best solution but it's the + * quickest. The best solution is to lazy-load the worker list. See also the + * issue #446. + */ +FlateWorker.prototype._createPako = function () { + this._pako = new pako[this._pakoAction]({ + raw: true, + level: this._pakoOptions.level || -1 // default compression + }); + var self = this; + this._pako.onData = function(data) { + self.push({ + data : data, + meta : self.meta + }); + }; +}; + +exports.compressWorker = function (compressionOptions) { + return new FlateWorker("Deflate", compressionOptions); +}; +exports.uncompressWorker = function () { + return new FlateWorker("Inflate", {}); +}; + +},{"./stream/GenericWorker":28,"./utils":32,"pako":59}],8:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); +var utf8 = require('../utf8'); +var crc32 = require('../crc32'); +var signature = require('../signature'); + +/** + * Transform an integer into a string in hexadecimal. + * @private + * @param {number} dec the number to convert. + * @param {number} bytes the number of bytes to generate. + * @returns {string} the result. + */ +var decToHex = function(dec, bytes) { + var hex = "", i; + for (i = 0; i < bytes; i++) { + hex += String.fromCharCode(dec & 0xff); + dec = dec >>> 8; + } + return hex; +}; + +/** + * Generate the UNIX part of the external file attributes. + * @param {Object} unixPermissions the unix permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : + * + * TTTTsstrwxrwxrwx0000000000ADVSHR + * ^^^^____________________________ file type, see zipinfo.c (UNX_*) + * ^^^_________________________ setuid, setgid, sticky + * ^^^^^^^^^________________ permissions + * ^^^^^^^^^^______ not used ? + * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only + */ +var generateUnixExternalFileAttr = function (unixPermissions, isDir) { + + var result = unixPermissions; + if (!unixPermissions) { + // I can't use octal values in strict mode, hence the hexa. + // 040775 => 0x41fd + // 0100664 => 0x81b4 + result = isDir ? 0x41fd : 0x81b4; + } + return (result & 0xFFFF) << 16; +}; + +/** + * Generate the DOS part of the external file attributes. + * @param {Object} dosPermissions the dos permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * Bit 0 Read-Only + * Bit 1 Hidden + * Bit 2 System + * Bit 3 Volume Label + * Bit 4 Directory + * Bit 5 Archive + */ +var generateDosExternalFileAttr = function (dosPermissions, isDir) { + + // the dir flag is already set for compatibility + return (dosPermissions || 0) & 0x3F; +}; + +/** + * Generate the various parts used in the construction of the final zip file. + * @param {Object} streamInfo the hash with informations about the compressed file. + * @param {Boolean} streamedContent is the content streamed ? + * @param {Boolean} streamingEnded is the stream finished ? + * @param {number} offset the current offset from the start of the zip file. + * @param {String} platform let's pretend we are this platform (change platform dependents fields) + * @param {Function} encodeFileName the function to encode the file name / comment. + * @return {Object} the zip parts. + */ +var generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) { + var file = streamInfo['file'], + compression = streamInfo['compression'], + useCustomEncoding = encodeFileName !== utf8.utf8encode, + encodedFileName = utils.transformTo("string", encodeFileName(file.name)), + utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), + comment = file.comment, + encodedComment = utils.transformTo("string", encodeFileName(comment)), + utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), + useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, + useUTF8ForComment = utfEncodedComment.length !== comment.length, + dosTime, + dosDate, + extraFields = "", + unicodePathExtraField = "", + unicodeCommentExtraField = "", + dir = file.dir, + date = file.date; + + + var dataInfo = { + crc32 : 0, + compressedSize : 0, + uncompressedSize : 0 + }; + + // if the content is streamed, the sizes/crc32 are only available AFTER + // the end of the stream. + if (!streamedContent || streamingEnded) { + dataInfo.crc32 = streamInfo['crc32']; + dataInfo.compressedSize = streamInfo['compressedSize']; + dataInfo.uncompressedSize = streamInfo['uncompressedSize']; + } + + var bitflag = 0; + if (streamedContent) { + // Bit 3: the sizes/crc32 are set to zero in the local header. + // The correct values are put in the data descriptor immediately + // following the compressed data. + bitflag |= 0x0008; + } + if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) { + // Bit 11: Language encoding flag (EFS). + bitflag |= 0x0800; + } + + + var extFileAttr = 0; + var versionMadeBy = 0; + if (dir) { + // dos or unix, we set the dos dir flag + extFileAttr |= 0x00010; + } + if(platform === "UNIX") { + versionMadeBy = 0x031E; // UNIX, version 3.0 + extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); + } else { // DOS or other, fallback to DOS + versionMadeBy = 0x0014; // DOS, version 2.0 + extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); + } + + // date + // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html + + dosTime = date.getUTCHours(); + dosTime = dosTime << 6; + dosTime = dosTime | date.getUTCMinutes(); + dosTime = dosTime << 5; + dosTime = dosTime | date.getUTCSeconds() / 2; + + dosDate = date.getUTCFullYear() - 1980; + dosDate = dosDate << 4; + dosDate = dosDate | (date.getUTCMonth() + 1); + dosDate = dosDate << 5; + dosDate = dosDate | date.getUTCDate(); + + if (useUTF8ForFileName) { + // set the unicode path extra field. unzip needs at least one extra + // field to correctly handle unicode path, so using the path is as good + // as any other information. This could improve the situation with + // other archive managers too. + // This field is usually used without the utf8 flag, with a non + // unicode path in the header (winrar, winzip). This helps (a bit) + // with the messy Windows' default compressed folders feature but + // breaks on p7zip which doesn't seek the unicode path extra field. + // So for now, UTF-8 everywhere ! + unicodePathExtraField = + // Version + decToHex(1, 1) + + // NameCRC32 + decToHex(crc32(encodedFileName), 4) + + // UnicodeName + utfEncodedFileName; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x70" + + // size + decToHex(unicodePathExtraField.length, 2) + + // content + unicodePathExtraField; + } + + if(useUTF8ForComment) { + + unicodeCommentExtraField = + // Version + decToHex(1, 1) + + // CommentCRC32 + decToHex(crc32(encodedComment), 4) + + // UnicodeName + utfEncodedComment; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x63" + + // size + decToHex(unicodeCommentExtraField.length, 2) + + // content + unicodeCommentExtraField; + } + + var header = ""; + + // version needed to extract + header += "\x0A\x00"; + // general purpose bit flag + header += decToHex(bitflag, 2); + // compression method + header += compression.magic; + // last mod file time + header += decToHex(dosTime, 2); + // last mod file date + header += decToHex(dosDate, 2); + // crc-32 + header += decToHex(dataInfo.crc32, 4); + // compressed size + header += decToHex(dataInfo.compressedSize, 4); + // uncompressed size + header += decToHex(dataInfo.uncompressedSize, 4); + // file name length + header += decToHex(encodedFileName.length, 2); + // extra field length + header += decToHex(extraFields.length, 2); + + + var fileRecord = signature.LOCAL_FILE_HEADER + header + encodedFileName + extraFields; + + var dirRecord = signature.CENTRAL_FILE_HEADER + + // version made by (00: DOS) + decToHex(versionMadeBy, 2) + + // file header (common to file and central directory) + header + + // file comment length + decToHex(encodedComment.length, 2) + + // disk number start + "\x00\x00" + + // internal file attributes TODO + "\x00\x00" + + // external file attributes + decToHex(extFileAttr, 4) + + // relative offset of local header + decToHex(offset, 4) + + // file name + encodedFileName + + // extra field + extraFields + + // file comment + encodedComment; + + return { + fileRecord: fileRecord, + dirRecord: dirRecord + }; +}; + +/** + * Generate the EOCD record. + * @param {Number} entriesCount the number of entries in the zip file. + * @param {Number} centralDirLength the length (in bytes) of the central dir. + * @param {Number} localDirLength the length (in bytes) of the local dir. + * @param {String} comment the zip file comment as a binary string. + * @param {Function} encodeFileName the function to encode the comment. + * @return {String} the EOCD record. + */ +var generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) { + var dirEnd = ""; + var encodedComment = utils.transformTo("string", encodeFileName(comment)); + + // end of central dir signature + dirEnd = signature.CENTRAL_DIRECTORY_END + + // number of this disk + "\x00\x00" + + // number of the disk with the start of the central directory + "\x00\x00" + + // total number of entries in the central directory on this disk + decToHex(entriesCount, 2) + + // total number of entries in the central directory + decToHex(entriesCount, 2) + + // size of the central directory 4 bytes + decToHex(centralDirLength, 4) + + // offset of start of central directory with respect to the starting disk number + decToHex(localDirLength, 4) + + // .ZIP file comment length + decToHex(encodedComment.length, 2) + + // .ZIP file comment + encodedComment; + + return dirEnd; +}; + +/** + * Generate data descriptors for a file entry. + * @param {Object} streamInfo the hash generated by a worker, containing informations + * on the file entry. + * @return {String} the data descriptors. + */ +var generateDataDescriptors = function (streamInfo) { + var descriptor = ""; + descriptor = signature.DATA_DESCRIPTOR + + // crc-32 4 bytes + decToHex(streamInfo['crc32'], 4) + + // compressed size 4 bytes + decToHex(streamInfo['compressedSize'], 4) + + // uncompressed size 4 bytes + decToHex(streamInfo['uncompressedSize'], 4); + + return descriptor; +}; + + +/** + * A worker to concatenate other workers to create a zip file. + * @param {Boolean} streamFiles `true` to stream the content of the files, + * `false` to accumulate it. + * @param {String} comment the comment to use. + * @param {String} platform the platform to use, "UNIX" or "DOS". + * @param {Function} encodeFileName the function to encode file names and comments. + */ +function ZipFileWorker(streamFiles, comment, platform, encodeFileName) { + GenericWorker.call(this, "ZipFileWorker"); + // The number of bytes written so far. This doesn't count accumulated chunks. + this.bytesWritten = 0; + // The comment of the zip file + this.zipComment = comment; + // The platform "generating" the zip file. + this.zipPlatform = platform; + // the function to encode file names and comments. + this.encodeFileName = encodeFileName; + // Should we stream the content of the files ? + this.streamFiles = streamFiles; + // If `streamFiles` is false, we will need to accumulate the content of the + // files to calculate sizes / crc32 (and write them *before* the content). + // This boolean indicates if we are accumulating chunks (it will change a lot + // during the lifetime of this worker). + this.accumulate = false; + // The buffer receiving chunks when accumulating content. + this.contentBuffer = []; + // The list of generated directory records. + this.dirRecords = []; + // The offset (in bytes) from the beginning of the zip file for the current source. + this.currentSourceOffset = 0; + // The total number of entries in this zip file. + this.entriesCount = 0; + // the name of the file currently being added, null when handling the end of the zip file. + // Used for the emited metadata. + this.currentFile = null; + + + + this._sources = []; +} +utils.inherits(ZipFileWorker, GenericWorker); + +/** + * @see GenericWorker.push + */ +ZipFileWorker.prototype.push = function (chunk) { + + var currentFilePercent = chunk.meta.percent || 0; + var entriesCount = this.entriesCount; + var remainingFiles = this._sources.length; + + if(this.accumulate) { + this.contentBuffer.push(chunk); + } else { + this.bytesWritten += chunk.data.length; + + GenericWorker.prototype.push.call(this, { + data : chunk.data, + meta : { + currentFile : this.currentFile, + percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100 + } + }); + } +}; + +/** + * The worker started a new source (an other worker). + * @param {Object} streamInfo the streamInfo object from the new source. + */ +ZipFileWorker.prototype.openedSource = function (streamInfo) { + this.currentSourceOffset = this.bytesWritten; + this.currentFile = streamInfo['file'].name; + + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + + // don't stream folders (because they don't have any content) + if(streamedContent) { + var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + } else { + // we need to wait for the whole file before pushing anything + this.accumulate = true; + } +}; + +/** + * The worker finished a source (an other worker). + * @param {Object} streamInfo the streamInfo object from the finished source. + */ +ZipFileWorker.prototype.closedSource = function (streamInfo) { + this.accumulate = false; + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + + this.dirRecords.push(record.dirRecord); + if(streamedContent) { + // after the streamed file, we put data descriptors + this.push({ + data : generateDataDescriptors(streamInfo), + meta : {percent:100} + }); + } else { + // the content wasn't streamed, we need to push everything now + // first the file record, then the content + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + while(this.contentBuffer.length) { + this.push(this.contentBuffer.shift()); + } + } + this.currentFile = null; +}; + +/** + * @see GenericWorker.flush + */ +ZipFileWorker.prototype.flush = function () { + + var localDirLength = this.bytesWritten; + for(var i = 0; i < this.dirRecords.length; i++) { + this.push({ + data : this.dirRecords[i], + meta : {percent:100} + }); + } + var centralDirLength = this.bytesWritten - localDirLength; + + var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName); + + this.push({ + data : dirEnd, + meta : {percent:100} + }); +}; + +/** + * Prepare the next source to be read. + */ +ZipFileWorker.prototype.prepareNextSource = function () { + this.previous = this._sources.shift(); + this.openedSource(this.previous.streamInfo); + if (this.isPaused) { + this.previous.pause(); + } else { + this.previous.resume(); + } +}; + +/** + * @see GenericWorker.registerPrevious + */ +ZipFileWorker.prototype.registerPrevious = function (previous) { + this._sources.push(previous); + var self = this; + + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.closedSource(self.previous.streamInfo); + if(self._sources.length) { + self.prepareNextSource(); + } else { + self.end(); + } + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; +}; + +/** + * @see GenericWorker.resume + */ +ZipFileWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this.previous && this._sources.length) { + this.prepareNextSource(); + return true; + } + if (!this.previous && !this._sources.length && !this.generatedError) { + this.end(); + return true; + } +}; + +/** + * @see GenericWorker.error + */ +ZipFileWorker.prototype.error = function (e) { + var sources = this._sources; + if(!GenericWorker.prototype.error.call(this, e)) { + return false; + } + for(var i = 0; i < sources.length; i++) { + try { + sources[i].error(e); + } catch(e) { + // the `error` exploded, nothing to do + } + } + return true; +}; + +/** + * @see GenericWorker.lock + */ +ZipFileWorker.prototype.lock = function () { + GenericWorker.prototype.lock.call(this); + var sources = this._sources; + for(var i = 0; i < sources.length; i++) { + sources[i].lock(); + } +}; + +module.exports = ZipFileWorker; + +},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(require,module,exports){ +'use strict'; + +var compressions = require('../compressions'); +var ZipFileWorker = require('./ZipFileWorker'); + +/** + * Find the compression to use. + * @param {String} fileCompression the compression defined at the file level, if any. + * @param {String} zipCompression the compression defined at the load() level. + * @return {Object} the compression object to use. + */ +var getCompression = function (fileCompression, zipCompression) { + + var compressionName = fileCompression || zipCompression; + var compression = compressions[compressionName]; + if (!compression) { + throw new Error(compressionName + " is not a valid compression method !"); + } + return compression; +}; + +/** + * Create a worker to generate a zip file. + * @param {JSZip} zip the JSZip instance at the right root level. + * @param {Object} options to generate the zip file. + * @param {String} comment the comment to use. + */ +exports.generateWorker = function (zip, options, comment) { + + var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName); + var entriesCount = 0; + try { + + zip.forEach(function (relativePath, file) { + entriesCount++; + var compression = getCompression(file.options.compression, options.compression); + var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; + var dir = file.dir, date = file.date; + + file._compressWorker(compression, compressionOptions) + .withStreamInfo("file", { + name : relativePath, + dir : dir, + date : date, + comment : file.comment || "", + unixPermissions : file.unixPermissions, + dosPermissions : file.dosPermissions + }) + .pipe(zipFileWorker); + }); + zipFileWorker.entriesCount = entriesCount; + } catch (e) { + zipFileWorker.error(e); + } + + return zipFileWorker; +}; + +},{"../compressions":3,"./ZipFileWorker":8}],10:[function(require,module,exports){ +'use strict'; + +/** + * Representation a of zip file in js + * @constructor + */ +function JSZip() { + // if this constructor is used without `new`, it adds `new` before itself: + if(!(this instanceof JSZip)) { + return new JSZip(); + } + + if(arguments.length) { + throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); + } + + // object containing the files : + // { + // "folder/" : {...}, + // "folder/data.txt" : {...} + // } + this.files = {}; + + this.comment = null; + + // Where we are in the hierarchy + this.root = ""; + this.clone = function() { + var newObj = new JSZip(); + for (var i in this) { + if (typeof this[i] !== "function") { + newObj[i] = this[i]; + } + } + return newObj; + }; +} +JSZip.prototype = require('./object'); +JSZip.prototype.loadAsync = require('./load'); +JSZip.support = require('./support'); +JSZip.defaults = require('./defaults'); + +// TODO find a better way to handle this version, +// a require('package.json').version doesn't work with webpack, see #327 +JSZip.version = "3.1.5"; + +JSZip.loadAsync = function (content, options) { + return new JSZip().loadAsync(content, options); +}; + +JSZip.external = require("./external"); +module.exports = JSZip; + +},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(require,module,exports){ +'use strict'; +var utils = require('./utils'); +var external = require("./external"); +var utf8 = require('./utf8'); +var utils = require('./utils'); +var ZipEntries = require('./zipEntries'); +var Crc32Probe = require('./stream/Crc32Probe'); +var nodejsUtils = require("./nodejsUtils"); + +/** + * Check the CRC32 of an entry. + * @param {ZipEntry} zipEntry the zip entry to check. + * @return {Promise} the result. + */ +function checkEntryCRC32(zipEntry) { + return new external.Promise(function (resolve, reject) { + var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe()); + worker.on("error", function (e) { + reject(e); + }) + .on("end", function () { + if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) { + reject(new Error("Corrupted zip : CRC32 mismatch")); + } else { + resolve(); + } + }) + .resume(); + }); +} + +module.exports = function(data, options) { + var zip = this; + options = utils.extend(options || {}, { + base64: false, + checkCRC32: false, + optimizedBinaryString: false, + createFolders: false, + decodeFileName: utf8.utf8decode + }); + + if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + return external.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")); + } + + return utils.prepareContent("the loaded zip file", data, true, options.optimizedBinaryString, options.base64) + .then(function(data) { + var zipEntries = new ZipEntries(options); + zipEntries.load(data); + return zipEntries; + }).then(function checkCRC32(zipEntries) { + var promises = [external.Promise.resolve(zipEntries)]; + var files = zipEntries.files; + if (options.checkCRC32) { + for (var i = 0; i < files.length; i++) { + promises.push(checkEntryCRC32(files[i])); + } + } + return external.Promise.all(promises); + }).then(function addFiles(results) { + var zipEntries = results.shift(); + var files = zipEntries.files; + for (var i = 0; i < files.length; i++) { + var input = files[i]; + zip.file(input.fileNameStr, input.decompressed, { + binary: true, + optimizedBinaryString: true, + date: input.date, + dir: input.dir, + comment : input.fileCommentStr.length ? input.fileCommentStr : null, + unixPermissions : input.unixPermissions, + dosPermissions : input.dosPermissions, + createFolders: options.createFolders + }); + } + if (zipEntries.zipComment.length) { + zip.comment = zipEntries.zipComment; + } + + return zip; + }); +}; + +},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(require,module,exports){ +"use strict"; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); + +/** + * A worker that use a nodejs stream as source. + * @constructor + * @param {String} filename the name of the file entry for this stream. + * @param {Readable} stream the nodejs stream. + */ +function NodejsStreamInputAdapter(filename, stream) { + GenericWorker.call(this, "Nodejs stream input adapter for " + filename); + this._upstreamEnded = false; + this._bindStream(stream); +} + +utils.inherits(NodejsStreamInputAdapter, GenericWorker); + +/** + * Prepare the stream and bind the callbacks on it. + * Do this ASAP on node 0.10 ! A lazy binding doesn't always work. + * @param {Stream} stream the nodejs stream to use. + */ +NodejsStreamInputAdapter.prototype._bindStream = function (stream) { + var self = this; + this._stream = stream; + stream.pause(); + stream + .on("data", function (chunk) { + self.push({ + data: chunk, + meta : { + percent : 0 + } + }); + }) + .on("error", function (e) { + if(self.isPaused) { + this.generatedError = e; + } else { + self.error(e); + } + }) + .on("end", function () { + if(self.isPaused) { + self._upstreamEnded = true; + } else { + self.end(); + } + }); +}; +NodejsStreamInputAdapter.prototype.pause = function () { + if(!GenericWorker.prototype.pause.call(this)) { + return false; + } + this._stream.pause(); + return true; +}; +NodejsStreamInputAdapter.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if(this._upstreamEnded) { + this.end(); + } else { + this._stream.resume(); + } + + return true; +}; + +module.exports = NodejsStreamInputAdapter; + +},{"../stream/GenericWorker":28,"../utils":32}],13:[function(require,module,exports){ +'use strict'; + +var Readable = require('readable-stream').Readable; + +var utils = require('../utils'); +utils.inherits(NodejsStreamOutputAdapter, Readable); + +/** +* A nodejs stream using a worker as source. +* @see the SourceWrapper in http://nodejs.org/api/stream.html +* @constructor +* @param {StreamHelper} helper the helper wrapping the worker +* @param {Object} options the nodejs stream options +* @param {Function} updateCb the update callback. +*/ +function NodejsStreamOutputAdapter(helper, options, updateCb) { + Readable.call(this, options); + this._helper = helper; + + var self = this; + helper.on("data", function (data, meta) { + if (!self.push(data)) { + self._helper.pause(); + } + if(updateCb) { + updateCb(meta); + } + }) + .on("error", function(e) { + self.emit('error', e); + }) + .on("end", function () { + self.push(null); + }); +} + + +NodejsStreamOutputAdapter.prototype._read = function() { + this._helper.resume(); +}; + +module.exports = NodejsStreamOutputAdapter; + +},{"../utils":32,"readable-stream":16}],14:[function(require,module,exports){ +'use strict'; + +module.exports = { + /** + * True if this is running in Nodejs, will be undefined in a browser. + * In a browser, browserify won't include this file and the whole module + * will be resolved an empty object. + */ + isNode : typeof Buffer !== "undefined", + /** + * Create a new nodejs Buffer from an existing content. + * @param {Object} data the data to pass to the constructor. + * @param {String} encoding the encoding to use. + * @return {Buffer} a new Buffer. + */ + newBufferFrom: function(data, encoding) { + // XXX We can't use `Buffer.from` which comes from `Uint8Array.from` + // in nodejs v4 (< v.4.5). It's not the expected implementation (and + // has a different signature). + // see https://github.com/nodejs/node/issues/8053 + // A condition on nodejs' version won't solve the issue as we don't + // control the Buffer polyfills that may or may not be used. + return new Buffer(data, encoding); + }, + /** + * Create a new nodejs Buffer with the specified size. + * @param {Integer} size the size of the buffer. + * @return {Buffer} a new Buffer. + */ + allocBuffer: function (size) { + if (Buffer.alloc) { + return Buffer.alloc(size); + } else { + return new Buffer(size); + } + }, + /** + * Find out if an object is a Buffer. + * @param {Object} b the object to test. + * @return {Boolean} true if the object is a Buffer, false otherwise. + */ + isBuffer : function(b){ + return Buffer.isBuffer(b); + }, + + isStream : function (obj) { + return obj && + typeof obj.on === "function" && + typeof obj.pause === "function" && + typeof obj.resume === "function"; + } +}; + +},{}],15:[function(require,module,exports){ +'use strict'; +var utf8 = require('./utf8'); +var utils = require('./utils'); +var GenericWorker = require('./stream/GenericWorker'); +var StreamHelper = require('./stream/StreamHelper'); +var defaults = require('./defaults'); +var CompressedObject = require('./compressedObject'); +var ZipObject = require('./zipObject'); +var generate = require("./generate"); +var nodejsUtils = require("./nodejsUtils"); +var NodejsStreamInputAdapter = require("./nodejs/NodejsStreamInputAdapter"); + + +/** + * Add a file in the current folder. + * @private + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file + * @param {Object} originalOptions the options of the file + * @return {Object} the new file. + */ +var fileAdd = function(name, data, originalOptions) { + // be sure sub folders exist + var dataType = utils.getTypeOf(data), + parent; + + + /* + * Correct options. + */ + + var o = utils.extend(originalOptions || {}, defaults); + o.date = o.date || new Date(); + if (o.compression !== null) { + o.compression = o.compression.toUpperCase(); + } + + if (typeof o.unixPermissions === "string") { + o.unixPermissions = parseInt(o.unixPermissions, 8); + } + + // UNX_IFDIR 0040000 see zipinfo.c + if (o.unixPermissions && (o.unixPermissions & 0x4000)) { + o.dir = true; + } + // Bit 4 Directory + if (o.dosPermissions && (o.dosPermissions & 0x0010)) { + o.dir = true; + } + + if (o.dir) { + name = forceTrailingSlash(name); + } + if (o.createFolders && (parent = parentFolder(name))) { + folderAdd.call(this, parent, true); + } + + var isUnicodeString = dataType === "string" && o.binary === false && o.base64 === false; + if (!originalOptions || typeof originalOptions.binary === "undefined") { + o.binary = !isUnicodeString; + } + + + var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0; + + if (isCompressedEmpty || o.dir || !data || data.length === 0) { + o.base64 = false; + o.binary = true; + data = ""; + o.compression = "STORE"; + dataType = "string"; + } + + /* + * Convert content to fit. + */ + + var zipObjectContent = null; + if (data instanceof CompressedObject || data instanceof GenericWorker) { + zipObjectContent = data; + } else if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + zipObjectContent = new NodejsStreamInputAdapter(name, data); + } else { + zipObjectContent = utils.prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64); + } + + var object = new ZipObject(name, zipObjectContent, o); + this.files[name] = object; + /* + TODO: we can't throw an exception because we have async promises + (we can have a promise of a Date() for example) but returning a + promise is useless because file(name, data) returns the JSZip + object for chaining. Should we break that to allow the user + to catch the error ? + + return external.Promise.resolve(zipObjectContent) + .then(function () { + return object; + }); + */ +}; + +/** + * Find the parent folder of the path. + * @private + * @param {string} path the path to use + * @return {string} the parent folder, or "" + */ +var parentFolder = function (path) { + if (path.slice(-1) === '/') { + path = path.substring(0, path.length - 1); + } + var lastSlash = path.lastIndexOf('/'); + return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; +}; + +/** + * Returns the path with a slash at the end. + * @private + * @param {String} path the path to check. + * @return {String} the path with a trailing slash. + */ +var forceTrailingSlash = function(path) { + // Check the name ends with a / + if (path.slice(-1) !== "/") { + path += "/"; // IE doesn't like substr(-1) + } + return path; +}; + +/** + * Add a (sub) folder in the current folder. + * @private + * @param {string} name the folder's name + * @param {boolean=} [createFolders] If true, automatically create sub + * folders. Defaults to false. + * @return {Object} the new folder. + */ +var folderAdd = function(name, createFolders) { + createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders; + + name = forceTrailingSlash(name); + + // Does this folder already exist? + if (!this.files[name]) { + fileAdd.call(this, name, null, { + dir: true, + createFolders: createFolders + }); + } + return this.files[name]; +}; + +/** +* Cross-window, cross-Node-context regular expression detection +* @param {Object} object Anything +* @return {Boolean} true if the object is a regular expression, +* false otherwise +*/ +function isRegExp(object) { + return Object.prototype.toString.call(object) === "[object RegExp]"; +} + +// return the actual prototype of JSZip +var out = { + /** + * @see loadAsync + */ + load: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + + /** + * Call a callback function for each entry at this folder level. + * @param {Function} cb the callback function: + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + */ + forEach: function(cb) { + var filename, relativePath, file; + for (filename in this.files) { + if (!this.files.hasOwnProperty(filename)) { + continue; + } + file = this.files[filename]; + relativePath = filename.slice(this.root.length, filename.length); + if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root + cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn... + } + } + }, + + /** + * Filter nested files/folders with the specified function. + * @param {Function} search the predicate to use : + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + * @return {Array} An array of matching elements. + */ + filter: function(search) { + var result = []; + this.forEach(function (relativePath, entry) { + if (search(relativePath, entry)) { // the file matches the function + result.push(entry); + } + + }); + return result; + }, + + /** + * Add a file to the zip file, or search a file. + * @param {string|RegExp} name The name of the file to add (if data is defined), + * the name of the file to find (if no data) or a regex to match files. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded + * @param {Object} o File options + * @return {JSZip|Object|Array} this JSZip object (when adding a file), + * a file (when searching by string) or an array of files (when searching by regex). + */ + file: function(name, data, o) { + if (arguments.length === 1) { + if (isRegExp(name)) { + var regexp = name; + return this.filter(function(relativePath, file) { + return !file.dir && regexp.test(relativePath); + }); + } + else { // text + var obj = this.files[this.root + name]; + if (obj && !obj.dir) { + return obj; + } else { + return null; + } + } + } + else { // more than one argument : we have data ! + name = this.root + name; + fileAdd.call(this, name, data, o); + } + return this; + }, + + /** + * Add a directory to the zip file, or search. + * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. + * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. + */ + folder: function(arg) { + if (!arg) { + return this; + } + + if (isRegExp(arg)) { + return this.filter(function(relativePath, file) { + return file.dir && arg.test(relativePath); + }); + } + + // else, name is a new folder + var name = this.root + arg; + var newFolder = folderAdd.call(this, name); + + // Allow chaining by returning a new object with this folder as the root + var ret = this.clone(); + ret.root = newFolder.name; + return ret; + }, + + /** + * Delete a file, or a directory and all sub-files, from the zip + * @param {string} name the name of the file to delete + * @return {JSZip} this JSZip object + */ + remove: function(name) { + name = this.root + name; + var file = this.files[name]; + if (!file) { + // Look for any folders + if (name.slice(-1) !== "/") { + name += "/"; + } + file = this.files[name]; + } + + if (file && !file.dir) { + // file + delete this.files[name]; + } else { + // maybe a folder, delete recursively + var kids = this.filter(function(relativePath, file) { + return file.name.slice(0, name.length) === name; + }); + for (var i = 0; i < kids.length; i++) { + delete this.files[kids[i].name]; + } + } + + return this; + }, + + /** + * Generate the complete zip file + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file + */ + generate: function(options) { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + /** + * Generate the complete zip file as an internal stream. + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {StreamHelper} the streamed zip file. + */ + generateInternalStream: function(options) { + var worker, opts = {}; + try { + opts = utils.extend(options || {}, { + streamFiles: false, + compression: "STORE", + compressionOptions : null, + type: "", + platform: "DOS", + comment: null, + mimeType: 'application/zip', + encodeFileName: utf8.utf8encode + }); + + opts.type = opts.type.toLowerCase(); + opts.compression = opts.compression.toUpperCase(); + + // "binarystring" is prefered but the internals use "string". + if(opts.type === "binarystring") { + opts.type = "string"; + } + + if (!opts.type) { + throw new Error("No output type specified."); + } + + utils.checkSupport(opts.type); + + // accept nodejs `process.platform` + if( + opts.platform === 'darwin' || + opts.platform === 'freebsd' || + opts.platform === 'linux' || + opts.platform === 'sunos' + ) { + opts.platform = "UNIX"; + } + if (opts.platform === 'win32') { + opts.platform = "DOS"; + } + + var comment = opts.comment || this.comment || ""; + worker = generate.generateWorker(this, opts, comment); + } catch (e) { + worker = new GenericWorker("error"); + worker.error(e); + } + return new StreamHelper(worker, opts.type || "string", opts.mimeType); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateAsync: function(options, onUpdate) { + return this.generateInternalStream(options).accumulate(onUpdate); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateNodeStream: function(options, onUpdate) { + options = options || {}; + if (!options.type) { + options.type = "nodebuffer"; + } + return this.generateInternalStream(options).toNodejsStream(onUpdate); + } +}; +module.exports = out; + +},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(require,module,exports){ +/* + * This file is used by module bundlers (browserify/webpack/etc) when + * including a stream implementation. We use "readable-stream" to get a + * consistent behavior between nodejs versions but bundlers often have a shim + * for "stream". Using this shim greatly improve the compatibility and greatly + * reduce the final size of the bundle (only one stream implementation, not + * two). + */ +module.exports = require("stream"); + +},{"stream":undefined}],17:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function ArrayReader(data) { + DataReader.call(this, data); + for(var i = 0; i < this.data.length; i++) { + data[i] = data[i] & 0xFF; + } +} +utils.inherits(ArrayReader, DataReader); +/** + * @see DataReader.byteAt + */ +ArrayReader.prototype.byteAt = function(i) { + return this.data[this.zero + i]; +}; +/** + * @see DataReader.lastIndexOfSignature + */ +ArrayReader.prototype.lastIndexOfSignature = function(sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3); + for (var i = this.length - 4; i >= 0; --i) { + if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { + return i - this.zero; + } + } + + return -1; +}; +/** + * @see DataReader.readAndCheckSignature + */ +ArrayReader.prototype.readAndCheckSignature = function (sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3), + data = this.readData(4); + return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3]; +}; +/** + * @see DataReader.readData + */ +ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + return []; + } + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = ArrayReader; + +},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){ +'use strict'; +var utils = require('../utils'); + +function DataReader(data) { + this.data = data; // type : see implementation + this.length = data.length; + this.index = 0; + this.zero = 0; +} +DataReader.prototype = { + /** + * Check that the offset will not go too far. + * @param {string} offset the additional offset to check. + * @throws {Error} an Error if the offset is out of bounds. + */ + checkOffset: function(offset) { + this.checkIndex(this.index + offset); + }, + /** + * Check that the specified index will not be too far. + * @param {string} newIndex the index to check. + * @throws {Error} an Error if the index is out of bounds. + */ + checkIndex: function(newIndex) { + if (this.length < this.zero + newIndex || newIndex < 0) { + throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); + } + }, + /** + * Change the index. + * @param {number} newIndex The new index. + * @throws {Error} if the new index is out of the data. + */ + setIndex: function(newIndex) { + this.checkIndex(newIndex); + this.index = newIndex; + }, + /** + * Skip the next n bytes. + * @param {number} n the number of bytes to skip. + * @throws {Error} if the new index is out of the data. + */ + skip: function(n) { + this.setIndex(this.index + n); + }, + /** + * Get the byte at the specified index. + * @param {number} i the index to use. + * @return {number} a byte. + */ + byteAt: function(i) { + // see implementations + }, + /** + * Get the next number with a given byte size. + * @param {number} size the number of bytes to read. + * @return {number} the corresponding number. + */ + readInt: function(size) { + var result = 0, + i; + this.checkOffset(size); + for (i = this.index + size - 1; i >= this.index; i--) { + result = (result << 8) + this.byteAt(i); + } + this.index += size; + return result; + }, + /** + * Get the next string with a given byte size. + * @param {number} size the number of bytes to read. + * @return {string} the corresponding string. + */ + readString: function(size) { + return utils.transformTo("string", this.readData(size)); + }, + /** + * Get raw data without conversion, bytes. + * @param {number} size the number of bytes to read. + * @return {Object} the raw data, implementation specific. + */ + readData: function(size) { + // see implementations + }, + /** + * Find the last occurence of a zip signature (4 bytes). + * @param {string} sig the signature to find. + * @return {number} the index of the last occurence, -1 if not found. + */ + lastIndexOfSignature: function(sig) { + // see implementations + }, + /** + * Read the signature (4 bytes) at the current position and compare it with sig. + * @param {string} sig the expected signature + * @return {boolean} true if the signature matches, false otherwise. + */ + readAndCheckSignature: function(sig) { + // see implementations + }, + /** + * Get the next date. + * @return {Date} the date. + */ + readDate: function() { + var dostime = this.readInt(4); + return new Date(Date.UTC( + ((dostime >> 25) & 0x7f) + 1980, // year + ((dostime >> 21) & 0x0f) - 1, // month + (dostime >> 16) & 0x1f, // day + (dostime >> 11) & 0x1f, // hour + (dostime >> 5) & 0x3f, // minute + (dostime & 0x1f) << 1)); // second + } +}; +module.exports = DataReader; + +},{"../utils":32}],19:[function(require,module,exports){ +'use strict'; +var Uint8ArrayReader = require('./Uint8ArrayReader'); +var utils = require('../utils'); + +function NodeBufferReader(data) { + Uint8ArrayReader.call(this, data); +} +utils.inherits(NodeBufferReader, Uint8ArrayReader); + +/** + * @see DataReader.readData + */ +NodeBufferReader.prototype.readData = function(size) { + this.checkOffset(size); + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = NodeBufferReader; + +},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function StringReader(data) { + DataReader.call(this, data); +} +utils.inherits(StringReader, DataReader); +/** + * @see DataReader.byteAt + */ +StringReader.prototype.byteAt = function(i) { + return this.data.charCodeAt(this.zero + i); +}; +/** + * @see DataReader.lastIndexOfSignature + */ +StringReader.prototype.lastIndexOfSignature = function(sig) { + return this.data.lastIndexOf(sig) - this.zero; +}; +/** + * @see DataReader.readAndCheckSignature + */ +StringReader.prototype.readAndCheckSignature = function (sig) { + var data = this.readData(4); + return sig === data; +}; +/** + * @see DataReader.readData + */ +StringReader.prototype.readData = function(size) { + this.checkOffset(size); + // this will work because the constructor applied the "& 0xff" mask. + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = StringReader; + +},{"../utils":32,"./DataReader":18}],21:[function(require,module,exports){ +'use strict'; +var ArrayReader = require('./ArrayReader'); +var utils = require('../utils'); + +function Uint8ArrayReader(data) { + ArrayReader.call(this, data); +} +utils.inherits(Uint8ArrayReader, ArrayReader); +/** + * @see DataReader.readData + */ +Uint8ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. + return new Uint8Array(0); + } + var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = Uint8ArrayReader; + +},{"../utils":32,"./ArrayReader":17}],22:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var support = require('../support'); +var ArrayReader = require('./ArrayReader'); +var StringReader = require('./StringReader'); +var NodeBufferReader = require('./NodeBufferReader'); +var Uint8ArrayReader = require('./Uint8ArrayReader'); + +/** + * Create a reader adapted to the data. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read. + * @return {DataReader} the data reader. + */ +module.exports = function (data) { + var type = utils.getTypeOf(data); + utils.checkSupport(type); + if (type === "string" && !support.uint8array) { + return new StringReader(data); + } + if (type === "nodebuffer") { + return new NodeBufferReader(data); + } + if (support.uint8array) { + return new Uint8ArrayReader(utils.transformTo("uint8array", data)); + } + return new ArrayReader(utils.transformTo("array", data)); +}; + +},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(require,module,exports){ +'use strict'; +exports.LOCAL_FILE_HEADER = "PK\x03\x04"; +exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; +exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; +exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; +exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; +exports.DATA_DESCRIPTOR = "PK\x07\x08"; + +},{}],24:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var utils = require('../utils'); + +/** + * A worker which convert chunks to a specified type. + * @constructor + * @param {String} destType the destination type. + */ +function ConvertWorker(destType) { + GenericWorker.call(this, "ConvertWorker to " + destType); + this.destType = destType; +} +utils.inherits(ConvertWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +ConvertWorker.prototype.processChunk = function (chunk) { + this.push({ + data : utils.transformTo(this.destType, chunk.data), + meta : chunk.meta + }); +}; +module.exports = ConvertWorker; + +},{"../utils":32,"./GenericWorker":28}],25:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var crc32 = require('../crc32'); +var utils = require('../utils'); + +/** + * A worker which calculate the crc32 of the data flowing through. + * @constructor + */ +function Crc32Probe() { + GenericWorker.call(this, "Crc32Probe"); + this.withStreamInfo("crc32", 0); +} +utils.inherits(Crc32Probe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Crc32Probe.prototype.processChunk = function (chunk) { + this.streamInfo.crc32 = crc32(chunk.data, this.streamInfo.crc32 || 0); + this.push(chunk); +}; +module.exports = Crc32Probe; + +},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +/** + * A worker which calculate the total length of the data flowing through. + * @constructor + * @param {String} propName the name used to expose the length + */ +function DataLengthProbe(propName) { + GenericWorker.call(this, "DataLengthProbe for " + propName); + this.propName = propName; + this.withStreamInfo(propName, 0); +} +utils.inherits(DataLengthProbe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +DataLengthProbe.prototype.processChunk = function (chunk) { + if(chunk) { + var length = this.streamInfo[this.propName] || 0; + this.streamInfo[this.propName] = length + chunk.data.length; + } + GenericWorker.prototype.processChunk.call(this, chunk); +}; +module.exports = DataLengthProbe; + + +},{"../utils":32,"./GenericWorker":28}],27:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +// the size of the generated chunks +// TODO expose this as a public variable +var DEFAULT_BLOCK_SIZE = 16 * 1024; + +/** + * A worker that reads a content and emits chunks. + * @constructor + * @param {Promise} dataP the promise of the data to split + */ +function DataWorker(dataP) { + GenericWorker.call(this, "DataWorker"); + var self = this; + this.dataIsReady = false; + this.index = 0; + this.max = 0; + this.data = null; + this.type = ""; + + this._tickScheduled = false; + + dataP.then(function (data) { + self.dataIsReady = true; + self.data = data; + self.max = data && data.length || 0; + self.type = utils.getTypeOf(data); + if(!self.isPaused) { + self._tickAndRepeat(); + } + }, function (e) { + self.error(e); + }); +} + +utils.inherits(DataWorker, GenericWorker); + +/** + * @see GenericWorker.cleanUp + */ +DataWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this.data = null; +}; + +/** + * @see GenericWorker.resume + */ +DataWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this._tickScheduled && this.dataIsReady) { + this._tickScheduled = true; + utils.delay(this._tickAndRepeat, [], this); + } + return true; +}; + +/** + * Trigger a tick a schedule an other call to this function. + */ +DataWorker.prototype._tickAndRepeat = function() { + this._tickScheduled = false; + if(this.isPaused || this.isFinished) { + return; + } + this._tick(); + if(!this.isFinished) { + utils.delay(this._tickAndRepeat, [], this); + this._tickScheduled = true; + } +}; + +/** + * Read and push a chunk. + */ +DataWorker.prototype._tick = function() { + + if(this.isPaused || this.isFinished) { + return false; + } + + var size = DEFAULT_BLOCK_SIZE; + var data = null, nextIndex = Math.min(this.max, this.index + size); + if (this.index >= this.max) { + // EOF + return this.end(); + } else { + switch(this.type) { + case "string": + data = this.data.substring(this.index, nextIndex); + break; + case "uint8array": + data = this.data.subarray(this.index, nextIndex); + break; + case "array": + case "nodebuffer": + data = this.data.slice(this.index, nextIndex); + break; + } + this.index = nextIndex; + return this.push({ + data : data, + meta : { + percent : this.max ? this.index / this.max * 100 : 0 + } + }); + } +}; + +module.exports = DataWorker; + +},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){ +'use strict'; + +/** + * A worker that does nothing but passing chunks to the next one. This is like + * a nodejs stream but with some differences. On the good side : + * - it works on IE 6-9 without any issue / polyfill + * - it weights less than the full dependencies bundled with browserify + * - it forwards errors (no need to declare an error handler EVERYWHERE) + * + * A chunk is an object with 2 attributes : `meta` and `data`. The former is an + * object containing anything (`percent` for example), see each worker for more + * details. The latter is the real data (String, Uint8Array, etc). + * + * @constructor + * @param {String} name the name of the stream (mainly used for debugging purposes) + */ +function GenericWorker(name) { + // the name of the worker + this.name = name || "default"; + // an object containing metadata about the workers chain + this.streamInfo = {}; + // an error which happened when the worker was paused + this.generatedError = null; + // an object containing metadata to be merged by this worker into the general metadata + this.extraStreamInfo = {}; + // true if the stream is paused (and should not do anything), false otherwise + this.isPaused = true; + // true if the stream is finished (and should not do anything), false otherwise + this.isFinished = false; + // true if the stream is locked to prevent further structure updates (pipe), false otherwise + this.isLocked = false; + // the event listeners + this._listeners = { + 'data':[], + 'end':[], + 'error':[] + }; + // the previous worker, if any + this.previous = null; +} + +GenericWorker.prototype = { + /** + * Push a chunk to the next workers. + * @param {Object} chunk the chunk to push + */ + push : function (chunk) { + this.emit("data", chunk); + }, + /** + * End the stream. + * @return {Boolean} true if this call ended the worker, false otherwise. + */ + end : function () { + if (this.isFinished) { + return false; + } + + this.flush(); + try { + this.emit("end"); + this.cleanUp(); + this.isFinished = true; + } catch (e) { + this.emit("error", e); + } + return true; + }, + /** + * End the stream with an error. + * @param {Error} e the error which caused the premature end. + * @return {Boolean} true if this call ended the worker with an error, false otherwise. + */ + error : function (e) { + if (this.isFinished) { + return false; + } + + if(this.isPaused) { + this.generatedError = e; + } else { + this.isFinished = true; + + this.emit("error", e); + + // in the workers chain exploded in the middle of the chain, + // the error event will go downward but we also need to notify + // workers upward that there has been an error. + if(this.previous) { + this.previous.error(e); + } + + this.cleanUp(); + } + return true; + }, + /** + * Add a callback on an event. + * @param {String} name the name of the event (data, end, error) + * @param {Function} listener the function to call when the event is triggered + * @return {GenericWorker} the current object for chainability + */ + on : function (name, listener) { + this._listeners[name].push(listener); + return this; + }, + /** + * Clean any references when a worker is ending. + */ + cleanUp : function () { + this.streamInfo = this.generatedError = this.extraStreamInfo = null; + this._listeners = []; + }, + /** + * Trigger an event. This will call registered callback with the provided arg. + * @param {String} name the name of the event (data, end, error) + * @param {Object} arg the argument to call the callback with. + */ + emit : function (name, arg) { + if (this._listeners[name]) { + for(var i = 0; i < this._listeners[name].length; i++) { + this._listeners[name][i].call(this, arg); + } + } + }, + /** + * Chain a worker with an other. + * @param {Worker} next the worker receiving events from the current one. + * @return {worker} the next worker for chainability + */ + pipe : function (next) { + return next.registerPrevious(this); + }, + /** + * Same as `pipe` in the other direction. + * Using an API with `pipe(next)` is very easy. + * Implementing the API with the point of view of the next one registering + * a source is easier, see the ZipFileWorker. + * @param {Worker} previous the previous worker, sending events to this one + * @return {Worker} the current worker for chainability + */ + registerPrevious : function (previous) { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + + // sharing the streamInfo... + this.streamInfo = previous.streamInfo; + // ... and adding our own bits + this.mergeStreamInfo(); + this.previous = previous; + var self = this; + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.end(); + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; + }, + /** + * Pause the stream so it doesn't send events anymore. + * @return {Boolean} true if this call paused the worker, false otherwise. + */ + pause : function () { + if(this.isPaused || this.isFinished) { + return false; + } + this.isPaused = true; + + if(this.previous) { + this.previous.pause(); + } + return true; + }, + /** + * Resume a paused stream. + * @return {Boolean} true if this call resumed the worker, false otherwise. + */ + resume : function () { + if(!this.isPaused || this.isFinished) { + return false; + } + this.isPaused = false; + + // if true, the worker tried to resume but failed + var withError = false; + if(this.generatedError) { + this.error(this.generatedError); + withError = true; + } + if(this.previous) { + this.previous.resume(); + } + + return !withError; + }, + /** + * Flush any remaining bytes as the stream is ending. + */ + flush : function () {}, + /** + * Process a chunk. This is usually the method overridden. + * @param {Object} chunk the chunk to process. + */ + processChunk : function(chunk) { + this.push(chunk); + }, + /** + * Add a key/value to be added in the workers chain streamInfo once activated. + * @param {String} key the key to use + * @param {Object} value the associated value + * @return {Worker} the current worker for chainability + */ + withStreamInfo : function (key, value) { + this.extraStreamInfo[key] = value; + this.mergeStreamInfo(); + return this; + }, + /** + * Merge this worker's streamInfo into the chain's streamInfo. + */ + mergeStreamInfo : function () { + for(var key in this.extraStreamInfo) { + if (!this.extraStreamInfo.hasOwnProperty(key)) { + continue; + } + this.streamInfo[key] = this.extraStreamInfo[key]; + } + }, + + /** + * Lock the stream to prevent further updates on the workers chain. + * After calling this method, all calls to pipe will fail. + */ + lock: function () { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + this.isLocked = true; + if (this.previous) { + this.previous.lock(); + } + }, + + /** + * + * Pretty print the workers chain. + */ + toString : function () { + var me = "Worker " + this.name; + if (this.previous) { + return this.previous + " -> " + me; + } else { + return me; + } + } +}; + +module.exports = GenericWorker; + +},{}],29:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var ConvertWorker = require('./ConvertWorker'); +var GenericWorker = require('./GenericWorker'); +var base64 = require('../base64'); +var support = require("../support"); +var external = require("../external"); + +var NodejsStreamOutputAdapter = null; +if (support.nodestream) { + try { + NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter'); + } catch(e) {} +} + +/** + * Apply the final transformation of the data. If the user wants a Blob for + * example, it's easier to work with an U8intArray and finally do the + * ArrayBuffer/Blob conversion. + * @param {String} type the name of the final type + * @param {String|Uint8Array|Buffer} content the content to transform + * @param {String} mimeType the mime type of the content, if applicable. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. + */ +function transformZipOutput(type, content, mimeType) { + switch(type) { + case "blob" : + return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); + case "base64" : + return base64.encode(content); + default : + return utils.transformTo(type, content); + } +} + +/** + * Concatenate an array of data of the given type. + * @param {String} type the type of the data in the given array. + * @param {Array} dataArray the array containing the data chunks to concatenate + * @return {String|Uint8Array|Buffer} the concatenated data + * @throws Error if the asked type is unsupported + */ +function concat (type, dataArray) { + var i, index = 0, res = null, totalLength = 0; + for(i = 0; i < dataArray.length; i++) { + totalLength += dataArray[i].length; + } + switch(type) { + case "string": + return dataArray.join(""); + case "array": + return Array.prototype.concat.apply([], dataArray); + case "uint8array": + res = new Uint8Array(totalLength); + for(i = 0; i < dataArray.length; i++) { + res.set(dataArray[i], index); + index += dataArray[i].length; + } + return res; + case "nodebuffer": + return Buffer.concat(dataArray); + default: + throw new Error("concat : unsupported type '" + type + "'"); + } +} + +/** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {StreamHelper} helper the helper to use. + * @param {Function} updateCallback a callback called on each update. Called + * with one arg : + * - the metadata linked to the update received. + * @return Promise the promise for the accumulation. + */ +function accumulate(helper, updateCallback) { + return new external.Promise(function (resolve, reject){ + var dataArray = []; + var chunkType = helper._internalType, + resultType = helper._outputType, + mimeType = helper._mimeType; + helper + .on('data', function (data, meta) { + dataArray.push(data); + if(updateCallback) { + updateCallback(meta); + } + }) + .on('error', function(err) { + dataArray = []; + reject(err); + }) + .on('end', function (){ + try { + var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); + resolve(result); + } catch (e) { + reject(e); + } + dataArray = []; + }) + .resume(); + }); +} + +/** + * An helper to easily use workers outside of JSZip. + * @constructor + * @param {Worker} worker the worker to wrap + * @param {String} outputType the type of data expected by the use + * @param {String} mimeType the mime type of the content, if applicable. + */ +function StreamHelper(worker, outputType, mimeType) { + var internalType = outputType; + switch(outputType) { + case "blob": + case "arraybuffer": + internalType = "uint8array"; + break; + case "base64": + internalType = "string"; + break; + } + + try { + // the type used internally + this._internalType = internalType; + // the type used to output results + this._outputType = outputType; + // the mime type + this._mimeType = mimeType; + utils.checkSupport(internalType); + this._worker = worker.pipe(new ConvertWorker(internalType)); + // the last workers can be rewired without issues but we need to + // prevent any updates on previous workers. + worker.lock(); + } catch(e) { + this._worker = new GenericWorker("error"); + this._worker.error(e); + } +} + +StreamHelper.prototype = { + /** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {Function} updateCb the update callback. + * @return Promise the promise for the accumulation. + */ + accumulate : function (updateCb) { + return accumulate(this, updateCb); + }, + /** + * Add a listener on an event triggered on a stream. + * @param {String} evt the name of the event + * @param {Function} fn the listener + * @return {StreamHelper} the current helper. + */ + on : function (evt, fn) { + var self = this; + + if(evt === "data") { + this._worker.on(evt, function (chunk) { + fn.call(self, chunk.data, chunk.meta); + }); + } else { + this._worker.on(evt, function () { + utils.delay(fn, arguments, self); + }); + } + return this; + }, + /** + * Resume the flow of chunks. + * @return {StreamHelper} the current helper. + */ + resume : function () { + utils.delay(this._worker.resume, [], this._worker); + return this; + }, + /** + * Pause the flow of chunks. + * @return {StreamHelper} the current helper. + */ + pause : function () { + this._worker.pause(); + return this; + }, + /** + * Return a nodejs stream for this helper. + * @param {Function} updateCb the update callback. + * @return {NodejsStreamOutputAdapter} the nodejs stream. + */ + toNodejsStream : function (updateCb) { + utils.checkSupport("nodestream"); + if (this._outputType !== "nodebuffer") { + // an object stream containing blob/arraybuffer/uint8array/string + // is strange and I don't know if it would be useful. + // I you find this comment and have a good usecase, please open a + // bug report ! + throw new Error(this._outputType + " is not supported by this method"); + } + + return new NodejsStreamOutputAdapter(this, { + objectMode : this._outputType !== "nodebuffer" + }, updateCb); + } +}; + + +module.exports = StreamHelper; + +},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(require,module,exports){ +'use strict'; + +exports.base64 = true; +exports.array = true; +exports.string = true; +exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; +exports.nodebuffer = typeof Buffer !== "undefined"; +// contains true if JSZip can read/generate Uint8Array, false otherwise. +exports.uint8array = typeof Uint8Array !== "undefined"; + +if (typeof ArrayBuffer === "undefined") { + exports.blob = false; +} +else { + var buffer = new ArrayBuffer(0); + try { + exports.blob = new Blob([buffer], { + type: "application/zip" + }).size === 0; + } + catch (e) { + try { + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + exports.blob = builder.getBlob('application/zip').size === 0; + } + catch (e) { + exports.blob = false; + } + } +} + +try { + exports.nodestream = !!require('readable-stream').Readable; +} catch(e) { + exports.nodestream = false; +} + +},{"readable-stream":16}],31:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var support = require('./support'); +var nodejsUtils = require('./nodejsUtils'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * The following functions come from pako, from pako/lib/utils/strings + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new Array(256); +for (var i=0; i<256; i++) { + _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); +} +_utf8len[254]=_utf8len[254]=1; // Invalid sequence start + +// convert string to array (typed, when possible) +var string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + if (support.uint8array) { + buf = new Uint8Array(buf_len); + } else { + buf = new Array(buf_len); + } + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +var utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +// convert array to string +var buf2string = function (buf) { + var str, i, out, c, c_len; + var len = buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + // shrinkBuf(utf16buf, out) + if (utf16buf.length !== out) { + if(utf16buf.subarray) { + utf16buf = utf16buf.subarray(0, out); + } else { + utf16buf.length = out; + } + } + + // return String.fromCharCode.apply(null, utf16buf); + return utils.applyFromCharCode(utf16buf); +}; + + +// That's all for the pako functions. + + +/** + * Transform a javascript string into an array (typed if possible) of bytes, + * UTF-8 encoded. + * @param {String} str the string to encode + * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. + */ +exports.utf8encode = function utf8encode(str) { + if (support.nodebuffer) { + return nodejsUtils.newBufferFrom(str, "utf-8"); + } + + return string2buf(str); +}; + + +/** + * Transform a bytes array (or a representation) representing an UTF-8 encoded + * string into a javascript string. + * @param {Array|Uint8Array|Buffer} buf the data de decode + * @return {String} the decoded string. + */ +exports.utf8decode = function utf8decode(buf) { + if (support.nodebuffer) { + return utils.transformTo("nodebuffer", buf).toString("utf-8"); + } + + buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); + + return buf2string(buf); +}; + +/** + * A worker to decode utf8 encoded binary chunks into string chunks. + * @constructor + */ +function Utf8DecodeWorker() { + GenericWorker.call(this, "utf-8 decode"); + // the last bytes if a chunk didn't end with a complete codepoint. + this.leftOver = null; +} +utils.inherits(Utf8DecodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8DecodeWorker.prototype.processChunk = function (chunk) { + + var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data); + + // 1st step, re-use what's left of the previous chunk + if (this.leftOver && this.leftOver.length) { + if(support.uint8array) { + var previousData = data; + data = new Uint8Array(previousData.length + this.leftOver.length); + data.set(this.leftOver, 0); + data.set(previousData, this.leftOver.length); + } else { + data = this.leftOver.concat(data); + } + this.leftOver = null; + } + + var nextBoundary = utf8border(data); + var usableData = data; + if (nextBoundary !== data.length) { + if (support.uint8array) { + usableData = data.subarray(0, nextBoundary); + this.leftOver = data.subarray(nextBoundary, data.length); + } else { + usableData = data.slice(0, nextBoundary); + this.leftOver = data.slice(nextBoundary, data.length); + } + } + + this.push({ + data : exports.utf8decode(usableData), + meta : chunk.meta + }); +}; + +/** + * @see GenericWorker.flush + */ +Utf8DecodeWorker.prototype.flush = function () { + if(this.leftOver && this.leftOver.length) { + this.push({ + data : exports.utf8decode(this.leftOver), + meta : {} + }); + this.leftOver = null; + } +}; +exports.Utf8DecodeWorker = Utf8DecodeWorker; + +/** + * A worker to endcode string chunks into utf8 encoded binary chunks. + * @constructor + */ +function Utf8EncodeWorker() { + GenericWorker.call(this, "utf-8 encode"); +} +utils.inherits(Utf8EncodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8EncodeWorker.prototype.processChunk = function (chunk) { + this.push({ + data : exports.utf8encode(chunk.data), + meta : chunk.meta + }); +}; +exports.Utf8EncodeWorker = Utf8EncodeWorker; + +},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){ +'use strict'; + +var support = require('./support'); +var base64 = require('./base64'); +var nodejsUtils = require('./nodejsUtils'); +var setImmediate = require('core-js/library/fn/set-immediate'); +var external = require("./external"); + + +/** + * Convert a string that pass as a "binary string": it should represent a byte + * array but may have > 255 char codes. Be sure to take only the first byte + * and returns the byte array. + * @param {String} str the string to transform. + * @return {Array|Uint8Array} the string in a binary format. + */ +function string2binary(str) { + var result = null; + if (support.uint8array) { + result = new Uint8Array(str.length); + } else { + result = new Array(str.length); + } + return stringToArrayLike(str, result); +} + +/** + * Create a new blob with the given content and the given type. + * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use + * an Uint8Array because the stock browser of android 4 won't accept it (it + * will be silently converted to a string, "[object Uint8Array]"). + * + * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: + * when a large amount of Array is used to create the Blob, the amount of + * memory consumed is nearly 100 times the original data amount. + * + * @param {String} type the mime type of the blob. + * @return {Blob} the created blob. + */ +exports.newBlob = function(part, type) { + exports.checkSupport("blob"); + + try { + // Blob constructor + return new Blob([part], { + type: type + }); + } + catch (e) { + + try { + // deprecated, browser only, old way + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(part); + return builder.getBlob(type); + } + catch (e) { + + // well, fuck ?! + throw new Error("Bug : can't construct the Blob."); + } + } + + +}; +/** + * The identity function. + * @param {Object} input the input. + * @return {Object} the same input. + */ +function identity(input) { + return input; +} + +/** + * Fill in an array with a string. + * @param {String} str the string to use. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. + */ +function stringToArrayLike(str, array) { + for (var i = 0; i < str.length; ++i) { + array[i] = str.charCodeAt(i) & 0xFF; + } + return array; +} + +/** + * An helper for the function arrayLikeToString. + * This contains static informations and functions that + * can be optimized by the browser JIT compiler. + */ +var arrayToStringHelper = { + /** + * Transform an array of int into a string, chunk by chunk. + * See the performances notes on arrayLikeToString. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @param {String} type the type of the array. + * @param {Integer} chunk the chunk size. + * @return {String} the resulting string. + * @throws Error if the chunk is too big for the stack. + */ + stringifyByChunk: function(array, type, chunk) { + var result = [], k = 0, len = array.length; + // shortcut + if (len <= chunk) { + return String.fromCharCode.apply(null, array); + } + while (k < len) { + if (type === "array" || type === "nodebuffer") { + result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); + } + else { + result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); + } + k += chunk; + } + return result.join(""); + }, + /** + * Call String.fromCharCode on every item in the array. + * This is the naive implementation, which generate A LOT of intermediate string. + * This should be used when everything else fail. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ + stringifyByChar: function(array){ + var resultStr = ""; + for(var i = 0; i < array.length; i++) { + resultStr += String.fromCharCode(array[i]); + } + return resultStr; + }, + applyCanBeUsed : { + /** + * true if the browser accepts to use String.fromCharCode on Uint8Array + */ + uint8array : (function () { + try { + return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; + } catch (e) { + return false; + } + })(), + /** + * true if the browser accepts to use String.fromCharCode on nodejs Buffer. + */ + nodebuffer : (function () { + try { + return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; + } catch (e) { + return false; + } + })() + } +}; + +/** + * Transform an array-like object to a string. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ +function arrayLikeToString(array) { + // Performances notes : + // -------------------- + // String.fromCharCode.apply(null, array) is the fastest, see + // see http://jsperf.com/converting-a-uint8array-to-a-string/2 + // but the stack is limited (and we can get huge arrays !). + // + // result += String.fromCharCode(array[i]); generate too many strings ! + // + // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 + // TODO : we now have workers that split the work. Do we still need that ? + var chunk = 65536, + type = exports.getTypeOf(array), + canUseApply = true; + if (type === "uint8array") { + canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; + } else if (type === "nodebuffer") { + canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; + } + + if (canUseApply) { + while (chunk > 1) { + try { + return arrayToStringHelper.stringifyByChunk(array, type, chunk); + } catch (e) { + chunk = Math.floor(chunk / 2); + } + } + } + + // no apply or chunk error : slow and painful algorithm + // default browser on android 4.* + return arrayToStringHelper.stringifyByChar(array); +} + +exports.applyFromCharCode = arrayLikeToString; + + +/** + * Copy the data from an array-like to an other array-like. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. + */ +function arrayLikeToArrayLike(arrayFrom, arrayTo) { + for (var i = 0; i < arrayFrom.length; i++) { + arrayTo[i] = arrayFrom[i]; + } + return arrayTo; +} + +// a matrix containing functions to transform everything into everything. +var transform = {}; + +// string to ? +transform["string"] = { + "string": identity, + "array": function(input) { + return stringToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["string"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return stringToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": function(input) { + return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); + } +}; + +// array to ? +transform["array"] = { + "string": arrayLikeToString, + "array": identity, + "arraybuffer": function(input) { + return (new Uint8Array(input)).buffer; + }, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// arraybuffer to ? +transform["arraybuffer"] = { + "string": function(input) { + return arrayLikeToString(new Uint8Array(input)); + }, + "array": function(input) { + return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); + }, + "arraybuffer": identity, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(new Uint8Array(input)); + } +}; + +// uint8array to ? +transform["uint8array"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return input.buffer; + }, + "uint8array": identity, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// nodebuffer to ? +transform["nodebuffer"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["nodebuffer"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return arrayLikeToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": identity +}; + +/** + * Transform an input into any type. + * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. + * If no output type is specified, the unmodified input will be returned. + * @param {String} outputType the output type. + * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. + * @throws {Error} an Error if the browser doesn't support the requested output type. + */ +exports.transformTo = function(outputType, input) { + if (!input) { + // undefined, null, etc + // an empty string won't harm. + input = ""; + } + if (!outputType) { + return input; + } + exports.checkSupport(outputType); + var inputType = exports.getTypeOf(input); + var result = transform[inputType][outputType](input); + return result; +}; + +/** + * Return the type of the input. + * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. + * @param {Object} input the input to identify. + * @return {String} the (lowercase) type of the input. + */ +exports.getTypeOf = function(input) { + if (typeof input === "string") { + return "string"; + } + if (Object.prototype.toString.call(input) === "[object Array]") { + return "array"; + } + if (support.nodebuffer && nodejsUtils.isBuffer(input)) { + return "nodebuffer"; + } + if (support.uint8array && input instanceof Uint8Array) { + return "uint8array"; + } + if (support.arraybuffer && input instanceof ArrayBuffer) { + return "arraybuffer"; + } +}; + +/** + * Throw an exception if the type is not supported. + * @param {String} type the type to check. + * @throws {Error} an Error if the browser doesn't support the requested type. + */ +exports.checkSupport = function(type) { + var supported = support[type.toLowerCase()]; + if (!supported) { + throw new Error(type + " is not supported by this platform"); + } +}; + +exports.MAX_VALUE_16BITS = 65535; +exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 + +/** + * Prettify a string read as binary. + * @param {string} str the string to prettify. + * @return {string} a pretty string. + */ +exports.pretty = function(str) { + var res = '', + code, i; + for (i = 0; i < (str || "").length; i++) { + code = str.charCodeAt(i); + res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); + } + return res; +}; + +/** + * Defer the call of a function. + * @param {Function} callback the function to call asynchronously. + * @param {Array} args the arguments to give to the callback. + */ +exports.delay = function(callback, args, self) { + setImmediate(function () { + callback.apply(self || null, args || []); + }); +}; + +/** + * Extends a prototype with an other, without calling a constructor with + * side effects. Inspired by nodejs' `utils.inherits` + * @param {Function} ctor the constructor to augment + * @param {Function} superCtor the parent constructor to use + */ +exports.inherits = function (ctor, superCtor) { + var Obj = function() {}; + Obj.prototype = superCtor.prototype; + ctor.prototype = new Obj(); +}; + +/** + * Merge the objects passed as parameters into a new one. + * @private + * @param {...Object} var_args All objects to merge. + * @return {Object} a new object with the data of the others. + */ +exports.extend = function() { + var result = {}, i, attr; + for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers + for (attr in arguments[i]) { + if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { + result[attr] = arguments[i][attr]; + } + } + } + return result; +}; + +/** + * Transform arbitrary content into a Promise. + * @param {String} name a name for the content being processed. + * @param {Object} inputData the content to process. + * @param {Boolean} isBinary true if the content is not an unicode string + * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. + * @param {Boolean} isBase64 true if the string content is encoded with base64. + * @return {Promise} a promise in a format usable by JSZip. + */ +exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { + + // if inputData is already a promise, this flatten it. + var promise = external.Promise.resolve(inputData).then(function(data) { + + + var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); + + if (isBlob && typeof FileReader !== "undefined") { + return new external.Promise(function (resolve, reject) { + var reader = new FileReader(); + + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e.target.error); + }; + reader.readAsArrayBuffer(data); + }); + } else { + return data; + } + }); + + return promise.then(function(data) { + var dataType = exports.getTypeOf(data); + + if (!dataType) { + return external.Promise.reject( + new Error("Can't read the data of '" + name + "'. Is it " + + "in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") + ); + } + // special case : it's way easier to work with Uint8Array than with ArrayBuffer + if (dataType === "arraybuffer") { + data = exports.transformTo("uint8array", data); + } else if (dataType === "string") { + if (isBase64) { + data = base64.decode(data); + } + else if (isBinary) { + // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask + if (isOptimizedBinaryString !== true) { + // this is a string, not in a base64 format. + // Be sure that this is a correct "binary string" + data = string2binary(data); + } + } + } + return data; + }); +}; + +},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"core-js/library/fn/set-immediate":36}],33:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var sig = require('./signature'); +var ZipEntry = require('./zipEntry'); +var utf8 = require('./utf8'); +var support = require('./support'); +// class ZipEntries {{{ +/** + * All the entries in the zip file. + * @constructor + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntries(loadOptions) { + this.files = []; + this.loadOptions = loadOptions; +} +ZipEntries.prototype = { + /** + * Check that the reader is on the specified signature. + * @param {string} expectedSignature the expected signature. + * @throws {Error} if it is an other signature. + */ + checkSignature: function(expectedSignature) { + if (!this.reader.readAndCheckSignature(expectedSignature)) { + this.reader.index -= 4; + var signature = this.reader.readString(4); + throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); + } + }, + /** + * Check if the given signature is at the given index. + * @param {number} askedIndex the index to check. + * @param {string} expectedSignature the signature to expect. + * @return {boolean} true if the signature is here, false otherwise. + */ + isSignature: function(askedIndex, expectedSignature) { + var currentIndex = this.reader.index; + this.reader.setIndex(askedIndex); + var signature = this.reader.readString(4); + var result = signature === expectedSignature; + this.reader.setIndex(currentIndex); + return result; + }, + /** + * Read the end of the central directory. + */ + readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2); + this.diskWithCentralDirStart = this.reader.readInt(2); + this.centralDirRecordsOnThisDisk = this.reader.readInt(2); + this.centralDirRecords = this.reader.readInt(2); + this.centralDirSize = this.reader.readInt(4); + this.centralDirOffset = this.reader.readInt(4); + + this.zipCommentLength = this.reader.readInt(2); + // warning : the encoding depends of the system locale + // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. + // On a windows machine, this field is encoded with the localized windows code page. + var zipComment = this.reader.readData(this.zipCommentLength); + var decodeParamType = support.uint8array ? "uint8array" : "array"; + // To get consistent behavior with the generation part, we will assume that + // this is utf8 encoded unless specified otherwise. + var decodeContent = utils.transformTo(decodeParamType, zipComment); + this.zipComment = this.loadOptions.decodeFileName(decodeContent); + }, + /** + * Read the end of the Zip 64 central directory. + * Not merged with the method readEndOfCentral : + * The end of central can coexist with its Zip64 brother, + * I don't want to read the wrong number of bytes ! + */ + readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8); + this.reader.skip(4); + // this.versionMadeBy = this.reader.readString(2); + // this.versionNeeded = this.reader.readInt(2); + this.diskNumber = this.reader.readInt(4); + this.diskWithCentralDirStart = this.reader.readInt(4); + this.centralDirRecordsOnThisDisk = this.reader.readInt(8); + this.centralDirRecords = this.reader.readInt(8); + this.centralDirSize = this.reader.readInt(8); + this.centralDirOffset = this.reader.readInt(8); + + this.zip64ExtensibleData = {}; + var extraDataSize = this.zip64EndOfCentralSize - 44, + index = 0, + extraFieldId, + extraFieldLength, + extraFieldValue; + while (index < extraDataSize) { + extraFieldId = this.reader.readInt(2); + extraFieldLength = this.reader.readInt(4); + extraFieldValue = this.reader.readData(extraFieldLength); + this.zip64ExtensibleData[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Read the end of the Zip 64 central directory locator. + */ + readBlockZip64EndOfCentralLocator: function() { + this.diskWithZip64CentralDirStart = this.reader.readInt(4); + this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); + this.disksCount = this.reader.readInt(4); + if (this.disksCount > 1) { + throw new Error("Multi-volumes zip are not supported"); + } + }, + /** + * Read the local files, based on the offset read in the central part. + */ + readLocalFiles: function() { + var i, file; + for (i = 0; i < this.files.length; i++) { + file = this.files[i]; + this.reader.setIndex(file.localHeaderOffset); + this.checkSignature(sig.LOCAL_FILE_HEADER); + file.readLocalPart(this.reader); + file.handleUTF8(); + file.processAttributes(); + } + }, + /** + * Read the central directory. + */ + readCentralDir: function() { + var file; + + this.reader.setIndex(this.centralDirOffset); + while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) { + file = new ZipEntry({ + zip64: this.zip64 + }, this.loadOptions); + file.readCentralPart(this.reader); + this.files.push(file); + } + + if (this.centralDirRecords !== this.files.length) { + if (this.centralDirRecords !== 0 && this.files.length === 0) { + // We expected some records but couldn't find ANY. + // This is really suspicious, as if something went wrong. + throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); + } else { + // We found some records but not all. + // Something is wrong but we got something for the user: no error here. + // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length); + } + } + }, + /** + * Read the end of central directory. + */ + readEndOfCentral: function() { + var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); + if (offset < 0) { + // Check if the content is a truncated zip or complete garbage. + // A "LOCAL_FILE_HEADER" is not required at the beginning (auto + // extractible zip for example) but it can give a good hint. + // If an ajax request was used without responseType, we will also + // get unreadable data. + var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER); + + if (isGarbage) { + throw new Error("Can't find end of central directory : is this a zip file ? " + + "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"); + } else { + throw new Error("Corrupted zip: can't find end of central directory"); + } + + } + this.reader.setIndex(offset); + var endOfCentralDirOffset = offset; + this.checkSignature(sig.CENTRAL_DIRECTORY_END); + this.readBlockEndOfCentral(); + + + /* extract from the zip spec : + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + */ + if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { + this.zip64 = true; + + /* + Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from + the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents + all numbers as 64-bit double precision IEEE 754 floating point numbers. + So, we have 53bits for integers and bitwise operations treat everything as 32bits. + see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators + and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 + */ + + // should look for a zip64 EOCD locator + offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + if (offset < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + this.readBlockZip64EndOfCentralLocator(); + + // now the zip64 EOCD record + if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) { + // console.warn("ZIP64 end of central directory not where expected."); + this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + if (this.relativeOffsetEndOfZip64CentralDir < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); + } + } + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + this.readBlockZip64EndOfCentral(); + } + + var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize; + if (this.zip64) { + expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator + expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize; + } + + var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset; + + if (extraBytes > 0) { + // console.warn(extraBytes, "extra bytes at beginning or within zipfile"); + if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) { + // The offsets seem wrong, but we have something at the specified offset. + // So… we keep it. + } else { + // the offset is wrong, update the "zero" of the reader + // this happens if data has been prepended (crx files for example) + this.reader.zero = extraBytes; + } + } else if (extraBytes < 0) { + throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes."); + } + }, + prepareReader: function(data) { + this.reader = readerFor(data); + }, + /** + * Read a zip file and create ZipEntries. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. + */ + load: function(data) { + this.prepareReader(data); + this.readEndOfCentral(); + this.readCentralDir(); + this.readLocalFiles(); + } +}; +// }}} end of ZipEntries +module.exports = ZipEntries; + +},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var CompressedObject = require('./compressedObject'); +var crc32fn = require('./crc32'); +var utf8 = require('./utf8'); +var compressions = require('./compressions'); +var support = require('./support'); + +var MADE_BY_DOS = 0x00; +var MADE_BY_UNIX = 0x03; + +/** + * Find a compression registered in JSZip. + * @param {string} compressionMethod the method magic to find. + * @return {Object|null} the JSZip compression object, null if none found. + */ +var findCompression = function(compressionMethod) { + for (var method in compressions) { + if (!compressions.hasOwnProperty(method)) { + continue; + } + if (compressions[method].magic === compressionMethod) { + return compressions[method]; + } + } + return null; +}; + +// class ZipEntry {{{ +/** + * An entry in the zip file. + * @constructor + * @param {Object} options Options of the current file. + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntry(options, loadOptions) { + this.options = options; + this.loadOptions = loadOptions; +} +ZipEntry.prototype = { + /** + * say if the file is encrypted. + * @return {boolean} true if the file is encrypted, false otherwise. + */ + isEncrypted: function() { + // bit 1 is set + return (this.bitFlag & 0x0001) === 0x0001; + }, + /** + * say if the file has utf-8 filename/comment. + * @return {boolean} true if the filename/comment is in utf-8, false otherwise. + */ + useUTF8: function() { + // bit 11 is set + return (this.bitFlag & 0x0800) === 0x0800; + }, + /** + * Read the local part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readLocalPart: function(reader) { + var compression, localExtraFieldsLength; + + // we already know everything from the central dir ! + // If the central dir data are false, we are doomed. + // On the bright side, the local part is scary : zip64, data descriptors, both, etc. + // The less data we get here, the more reliable this should be. + // Let's skip the whole header and dash to the data ! + reader.skip(22); + // in some zip created on windows, the filename stored in the central dir contains \ instead of /. + // Strangely, the filename here is OK. + // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes + // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... + // Search "unzip mismatching "local" filename continuing with "central" filename version" on + // the internet. + // + // I think I see the logic here : the central directory is used to display + // content and the local directory is used to extract the files. Mixing / and \ + // may be used to display \ to windows users and use / when extracting the files. + // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 + this.fileNameLength = reader.readInt(2); + localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir + // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding. + this.fileName = reader.readData(this.fileNameLength); + reader.skip(localExtraFieldsLength); + + if (this.compressedSize === -1 || this.uncompressedSize === -1) { + throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)"); + } + + compression = findCompression(this.compressionMethod); + if (compression === null) { // no compression found + throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")"); + } + this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize)); + }, + + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readCentralPart: function(reader) { + this.versionMadeBy = reader.readInt(2); + reader.skip(2); + // this.versionNeeded = reader.readInt(2); + this.bitFlag = reader.readInt(2); + this.compressionMethod = reader.readString(2); + this.date = reader.readDate(); + this.crc32 = reader.readInt(4); + this.compressedSize = reader.readInt(4); + this.uncompressedSize = reader.readInt(4); + var fileNameLength = reader.readInt(2); + this.extraFieldsLength = reader.readInt(2); + this.fileCommentLength = reader.readInt(2); + this.diskNumberStart = reader.readInt(2); + this.internalFileAttributes = reader.readInt(2); + this.externalFileAttributes = reader.readInt(4); + this.localHeaderOffset = reader.readInt(4); + + if (this.isEncrypted()) { + throw new Error("Encrypted zip are not supported"); + } + + // will be read in the local part, see the comments there + reader.skip(fileNameLength); + this.readExtraFields(reader); + this.parseZIP64ExtraField(reader); + this.fileComment = reader.readData(this.fileCommentLength); + }, + + /** + * Parse the external file attributes and get the unix/dos permissions. + */ + processAttributes: function () { + this.unixPermissions = null; + this.dosPermissions = null; + var madeBy = this.versionMadeBy >> 8; + + // Check if we have the DOS directory flag set. + // We look for it in the DOS and UNIX permissions + // but some unknown platform could set it as a compatibility flag. + this.dir = this.externalFileAttributes & 0x0010 ? true : false; + + if(madeBy === MADE_BY_DOS) { + // first 6 bits (0 to 5) + this.dosPermissions = this.externalFileAttributes & 0x3F; + } + + if(madeBy === MADE_BY_UNIX) { + this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; + // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); + } + + // fail safe : if the name ends with a / it probably means a folder + if (!this.dir && this.fileNameStr.slice(-1) === '/') { + this.dir = true; + } + }, + + /** + * Parse the ZIP64 extra field and merge the info in the current ZipEntry. + * @param {DataReader} reader the reader to use. + */ + parseZIP64ExtraField: function(reader) { + + if (!this.extraFields[0x0001]) { + return; + } + + // should be something, preparing the extra reader + var extraReader = readerFor(this.extraFields[0x0001].value); + + // I really hope that these 64bits integer can fit in 32 bits integer, because js + // won't let us have more. + if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { + this.uncompressedSize = extraReader.readInt(8); + } + if (this.compressedSize === utils.MAX_VALUE_32BITS) { + this.compressedSize = extraReader.readInt(8); + } + if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { + this.localHeaderOffset = extraReader.readInt(8); + } + if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { + this.diskNumberStart = extraReader.readInt(4); + } + }, + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readExtraFields: function(reader) { + var end = reader.index + this.extraFieldsLength, + extraFieldId, + extraFieldLength, + extraFieldValue; + + if (!this.extraFields) { + this.extraFields = {}; + } + + while (reader.index < end) { + extraFieldId = reader.readInt(2); + extraFieldLength = reader.readInt(2); + extraFieldValue = reader.readData(extraFieldLength); + + this.extraFields[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Apply an UTF8 transformation if needed. + */ + handleUTF8: function() { + var decodeParamType = support.uint8array ? "uint8array" : "array"; + if (this.useUTF8()) { + this.fileNameStr = utf8.utf8decode(this.fileName); + this.fileCommentStr = utf8.utf8decode(this.fileComment); + } else { + var upath = this.findExtraFieldUnicodePath(); + if (upath !== null) { + this.fileNameStr = upath; + } else { + // ASCII text or unsupported code page + var fileNameByteArray = utils.transformTo(decodeParamType, this.fileName); + this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray); + } + + var ucomment = this.findExtraFieldUnicodeComment(); + if (ucomment !== null) { + this.fileCommentStr = ucomment; + } else { + // ASCII text or unsupported code page + var commentByteArray = utils.transformTo(decodeParamType, this.fileComment); + this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray); + } + } + }, + + /** + * Find the unicode path declared in the extra field, if any. + * @return {String} the unicode path, null otherwise. + */ + findExtraFieldUnicodePath: function() { + var upathField = this.extraFields[0x7075]; + if (upathField) { + var extraReader = readerFor(upathField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the filename changed, this field is out of date. + if (crc32fn(this.fileName) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(upathField.length - 5)); + } + return null; + }, + + /** + * Find the unicode comment declared in the extra field, if any. + * @return {String} the unicode comment, null otherwise. + */ + findExtraFieldUnicodeComment: function() { + var ucommentField = this.extraFields[0x6375]; + if (ucommentField) { + var extraReader = readerFor(ucommentField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the comment changed, this field is out of date. + if (crc32fn(this.fileComment) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(ucommentField.length - 5)); + } + return null; + } +}; +module.exports = ZipEntry; + +},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(require,module,exports){ +'use strict'; + +var StreamHelper = require('./stream/StreamHelper'); +var DataWorker = require('./stream/DataWorker'); +var utf8 = require('./utf8'); +var CompressedObject = require('./compressedObject'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * A simple object representing a file in the zip file. + * @constructor + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data + * @param {Object} options the options of the file + */ +var ZipObject = function(name, data, options) { + this.name = name; + this.dir = options.dir; + this.date = options.date; + this.comment = options.comment; + this.unixPermissions = options.unixPermissions; + this.dosPermissions = options.dosPermissions; + + this._data = data; + this._dataBinary = options.binary; + // keep only the compression + this.options = { + compression : options.compression, + compressionOptions : options.compressionOptions + }; +}; + +ZipObject.prototype = { + /** + * Create an internal stream for the content of this object. + * @param {String} type the type of each chunk. + * @return StreamHelper the stream. + */ + internalStream: function (type) { + var result = null, outputType = "string"; + try { + if (!type) { + throw new Error("No output type specified."); + } + outputType = type.toLowerCase(); + var askUnicodeString = outputType === "string" || outputType === "text"; + if (outputType === "binarystring" || outputType === "text") { + outputType = "string"; + } + result = this._decompressWorker(); + + var isUnicodeString = !this._dataBinary; + + if (isUnicodeString && !askUnicodeString) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + if (!isUnicodeString && askUnicodeString) { + result = result.pipe(new utf8.Utf8DecodeWorker()); + } + } catch (e) { + result = new GenericWorker("error"); + result.error(e); + } + + return new StreamHelper(result, outputType, ""); + }, + + /** + * Prepare the content in the asked type. + * @param {String} type the type of the result. + * @param {Function} onUpdate a function to call on each internal update. + * @return Promise the promise of the result. + */ + async: function (type, onUpdate) { + return this.internalStream(type).accumulate(onUpdate); + }, + + /** + * Prepare the content as a nodejs stream. + * @param {String} type the type of each chunk. + * @param {Function} onUpdate a function to call on each internal update. + * @return Stream the stream. + */ + nodeStream: function (type, onUpdate) { + return this.internalStream(type || "nodebuffer").toNodejsStream(onUpdate); + }, + + /** + * Return a worker for the compressed content. + * @private + * @param {Object} compression the compression object to use. + * @param {Object} compressionOptions the options to use when compressing. + * @return Worker the worker. + */ + _compressWorker: function (compression, compressionOptions) { + if ( + this._data instanceof CompressedObject && + this._data.compression.magic === compression.magic + ) { + return this._data.getCompressedWorker(); + } else { + var result = this._decompressWorker(); + if(!this._dataBinary) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + return CompressedObject.createWorkerFrom(result, compression, compressionOptions); + } + }, + /** + * Return a worker for the decompressed content. + * @private + * @return Worker the worker. + */ + _decompressWorker : function () { + if (this._data instanceof CompressedObject) { + return this._data.getContentWorker(); + } else if (this._data instanceof GenericWorker) { + return this._data; + } else { + return new DataWorker(this._data); + } + } +}; + +var removedMethods = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"]; +var removedFn = function () { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); +}; + +for(var i = 0; i < removedMethods.length; i++) { + ZipObject.prototype[removedMethods[i]] = removedFn; +} +module.exports = ZipObject; + +},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(require,module,exports){ +require('../modules/web.immediate'); +module.exports = require('../modules/_core').setImmediate; +},{"../modules/_core":40,"../modules/web.immediate":56}],37:[function(require,module,exports){ +module.exports = function(it){ + if(typeof it != 'function')throw TypeError(it + ' is not a function!'); + return it; +}; +},{}],38:[function(require,module,exports){ +var isObject = require('./_is-object'); +module.exports = function(it){ + if(!isObject(it))throw TypeError(it + ' is not an object!'); + return it; +}; +},{"./_is-object":51}],39:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = function(it){ + return toString.call(it).slice(8, -1); +}; +},{}],40:[function(require,module,exports){ +var core = module.exports = {version: '2.3.0'}; +if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef +},{}],41:[function(require,module,exports){ +// optional / simple context binding +var aFunction = require('./_a-function'); +module.exports = function(fn, that, length){ + aFunction(fn); + if(that === undefined)return fn; + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; +}; +},{"./_a-function":37}],42:[function(require,module,exports){ +// Thank's IE8 for his funny defineProperty +module.exports = !require('./_fails')(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_fails":45}],43:[function(require,module,exports){ +var isObject = require('./_is-object') + , document = require('./_global').document + // in old IE typeof document.createElement is 'object' + , is = isObject(document) && isObject(document.createElement); +module.exports = function(it){ + return is ? document.createElement(it) : {}; +}; +},{"./_global":46,"./_is-object":51}],44:[function(require,module,exports){ +var global = require('./_global') + , core = require('./_core') + , ctx = require('./_ctx') + , hide = require('./_hide') + , PROTOTYPE = 'prototype'; + +var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , IS_WRAP = type & $export.W + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] + , key, own, out; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if(own && key in exports)continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function(C){ + var F = function(a, b, c){ + if(this instanceof C){ + switch(arguments.length){ + case 0: return new C; + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if(IS_PROTO){ + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); + } + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; +},{"./_core":40,"./_ctx":41,"./_global":46,"./_hide":47}],45:[function(require,module,exports){ +module.exports = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } +}; +},{}],46:[function(require,module,exports){ +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); +if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef +},{}],47:[function(require,module,exports){ +var dP = require('./_object-dp') + , createDesc = require('./_property-desc'); +module.exports = require('./_descriptors') ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); +} : function(object, key, value){ + object[key] = value; + return object; +}; +},{"./_descriptors":42,"./_object-dp":52,"./_property-desc":53}],48:[function(require,module,exports){ +module.exports = require('./_global').document && document.documentElement; +},{"./_global":46}],49:[function(require,module,exports){ +module.exports = !require('./_descriptors') && !require('./_fails')(function(){ + return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_descriptors":42,"./_dom-create":43,"./_fails":45}],50:[function(require,module,exports){ +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function(fn, args, that){ + var un = that === undefined; + switch(args.length){ + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; +},{}],51:[function(require,module,exports){ +module.exports = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; +},{}],52:[function(require,module,exports){ +var anObject = require('./_an-object') + , IE8_DOM_DEFINE = require('./_ie8-dom-define') + , toPrimitive = require('./_to-primitive') + , dP = Object.defineProperty; + +exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){ + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if(IE8_DOM_DEFINE)try { + return dP(O, P, Attributes); + } catch(e){ /* empty */ } + if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); + if('value' in Attributes)O[P] = Attributes.value; + return O; +}; +},{"./_an-object":38,"./_descriptors":42,"./_ie8-dom-define":49,"./_to-primitive":55}],53:[function(require,module,exports){ +module.exports = function(bitmap, value){ + return { + enumerable : !(bitmap & 1), + configurable: !(bitmap & 2), + writable : !(bitmap & 4), + value : value + }; +}; +},{}],54:[function(require,module,exports){ +var ctx = require('./_ctx') + , invoke = require('./_invoke') + , html = require('./_html') + , cel = require('./_dom-create') + , global = require('./_global') + , process = global.process + , setTask = global.setImmediate + , clearTask = global.clearImmediate + , MessageChannel = global.MessageChannel + , counter = 0 + , queue = {} + , ONREADYSTATECHANGE = 'onreadystatechange' + , defer, channel, port; +var run = function(){ + var id = +this; + if(queue.hasOwnProperty(id)){ + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function(event){ + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if(!setTask || !clearTask){ + setTask = function setImmediate(fn){ + var args = [], i = 1; + while(arguments.length > i)args.push(arguments[i++]); + queue[++counter] = function(){ + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id){ + delete queue[id]; + }; + // Node.js 0.8- + if(require('./_cof')(process) == 'process'){ + defer = function(id){ + process.nextTick(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if(MessageChannel){ + channel = new MessageChannel; + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ + defer = function(id){ + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if(ONREADYSTATECHANGE in cel('script')){ + defer = function(id){ + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function(id){ + setTimeout(ctx(run, id, 1), 0); + }; + } +} +module.exports = { + set: setTask, + clear: clearTask +}; +},{"./_cof":39,"./_ctx":41,"./_dom-create":43,"./_global":46,"./_html":48,"./_invoke":50}],55:[function(require,module,exports){ +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = require('./_is-object'); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function(it, S){ + if(!isObject(it))return it; + var fn, val; + if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; + if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + throw TypeError("Can't convert object to primitive value"); +}; +},{"./_is-object":51}],56:[function(require,module,exports){ +var $export = require('./_export') + , $task = require('./_task'); +$export($export.G + $export.B, { + setImmediate: $task.set, + clearImmediate: $task.clear +}); +},{"./_export":44,"./_task":54}],57:[function(require,module,exports){ +(function (global){ +'use strict'; +var Mutation = global.MutationObserver || global.WebKitMutationObserver; + +var scheduleDrain; + +{ + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + scheduleDrain = function () { + element.data = (called = ++called % 2); + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + + // Create a + + - - +
    - -
    - - - - - - - -
    - - -
    -

    ACF (Sponge) 0.5.0-SNAPSHOT API

    -
    -
    - - - - - - - - - - - - - - - - - - - - -
    Packages 
    PackageDescription
    co.aikar.commands 
    co.aikar.commands.contexts 
    co.aikar.commands.sponge.contexts 
    -
    - -
    - - - - - - - -
    - - -

    Copyright © 2019. All rights reserved.

    +

    index.html

    +
    diff --git a/docs/acf-sponge/overview-tree.html b/docs/acf-sponge/overview-tree.html index d9d0affe..6dd91281 100644 --- a/docs/acf-sponge/overview-tree.html +++ b/docs/acf-sponge/overview-tree.html @@ -1,12 +1,21 @@ - + - Class Hierarchy (ACF (Sponge) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Hierarchy For All Packages

    Package Hierarchies: @@ -78,96 +102,103 @@
    +

    Class Hierarchy

    +
    +

    Enum Hierarchy

    +
    +
    + diff --git a/docs/acf-sponge/package-search-index.js b/docs/acf-sponge/package-search-index.js new file mode 100644 index 00000000..0638502b --- /dev/null +++ b/docs/acf-sponge/package-search-index.js @@ -0,0 +1 @@ +packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"co.aikar.commands"},{"l":"co.aikar.commands.contexts"},{"l":"co.aikar.commands.sponge.contexts"}] \ No newline at end of file diff --git a/docs/acf-sponge/package-search-index.zip b/docs/acf-sponge/package-search-index.zip new file mode 100644 index 00000000..6ea1b1a5 Binary files /dev/null and b/docs/acf-sponge/package-search-index.zip differ diff --git a/docs/acf-sponge/resources/glass.png b/docs/acf-sponge/resources/glass.png new file mode 100644 index 00000000..a7f591f4 Binary files /dev/null and b/docs/acf-sponge/resources/glass.png differ diff --git a/docs/acf-sponge/resources/x.png b/docs/acf-sponge/resources/x.png new file mode 100644 index 00000000..30548a75 Binary files /dev/null and b/docs/acf-sponge/resources/x.png differ diff --git a/docs/acf-sponge/script.js b/docs/acf-sponge/script.js index b3463569..0eaaf535 100644 --- a/docs/acf-sponge/script.js +++ b/docs/acf-sponge/script.js @@ -1,9 +1,114 @@ -function show(type) -{ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var moduleSearchIndex; +var packageSearchIndex; +var typeSearchIndex; +var memberSearchIndex; +var tagSearchIndex; +function loadScripts(doc, tag) { + createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); + if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || + window.navigator.userAgent.indexOf('Edge/') > 0) { + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); + } + createElem(doc, tag, 'search.js'); + + $.get(pathtoroot + "module-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + moduleSearchIndex = JSON.parse(zip.file("module-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "package-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + packageSearchIndex = JSON.parse(zip.file("package-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "type-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + typeSearchIndex = JSON.parse(zip.file("type-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "member-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + memberSearchIndex = JSON.parse(zip.file("member-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "tag-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + tagSearchIndex = JSON.parse(zip.file("tag-search-index.json").asText()); + }); + }); + if (!moduleSearchIndex) { + createElem(doc, tag, 'module-search-index.js'); + } + if (!packageSearchIndex) { + createElem(doc, tag, 'package-search-index.js'); + } + if (!typeSearchIndex) { + createElem(doc, tag, 'type-search-index.js'); + } + if (!memberSearchIndex) { + createElem(doc, tag, 'member-search-index.js'); + } + if (!tagSearchIndex) { + createElem(doc, tag, 'tag-search-index.js'); + } + $(window).resize(function() { + $('.navPadding').css('padding-top', $('.fixedNav').css("height")); + }); +} + +function createElem(doc, tag, path) { + var script = doc.createElement(tag); + var scriptElement = doc.getElementsByTagName(tag)[0]; + script.src = pathtoroot + path; + scriptElement.parentNode.insertBefore(script, scriptElement); +} + +function show(type) { count = 0; - for (var key in methods) { + for (var key in data) { var row = document.getElementById(key); - if ((methods[key] & type) != 0) { + if ((data[key] & type) !== 0) { row.style.display = ''; row.className = (count++ % 2) ? rowColor : altColor; } @@ -13,8 +118,7 @@ function show(type) updateTabs(type); } -function updateTabs(type) -{ +function updateTabs(type) { for (var value in tabs) { var sNode = document.getElementById(tabs[value][0]); var spanNode = sNode.firstChild; @@ -28,3 +132,8 @@ function updateTabs(type) } } } + +function updateModuleFrame(pFrame, cFrame) { + top.packageFrame.location = pFrame; + top.classFrame.location = cFrame; +} diff --git a/docs/acf-sponge/search.js b/docs/acf-sponge/search.js new file mode 100644 index 00000000..b773531b --- /dev/null +++ b/docs/acf-sponge/search.js @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var noResult = {l: "No results found"}; +var catModules = "Modules"; +var catPackages = "Packages"; +var catTypes = "Types"; +var catMembers = "Members"; +var catSearchTags = "SearchTags"; +var highlight = "$&"; +var camelCaseRegexp = ""; +var secondaryMatcher = ""; +function getHighlightedText(item) { + var ccMatcher = new RegExp(camelCaseRegexp); + var label = item.replace(ccMatcher, highlight); + if (label === item) { + label = item.replace(secondaryMatcher, highlight); + } + return label; +} +function getURLPrefix(ui) { + var urlPrefix=""; + if (useModuleDirectories) { + var slash = "/"; + if (ui.item.category === catModules) { + return ui.item.l + slash; + } else if (ui.item.category === catPackages && ui.item.m) { + return ui.item.m + slash; + } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { + $.each(packageSearchIndex, function(index, item) { + if (ui.item.p == item.l) { + urlPrefix = item.m + slash; + } + }); + return urlPrefix; + } else { + return urlPrefix; + } + } + return urlPrefix; +} +var watermark = 'Search'; +$(function() { + $("#search").val(''); + $("#search").prop("disabled", false); + $("#reset").prop("disabled", false); + $("#search").val(watermark).addClass('watermark'); + $("#search").blur(function() { + if ($(this).val().length == 0) { + $(this).val(watermark).addClass('watermark'); + } + }); + $("#search").on('click keydown', function() { + if ($(this).val() == watermark) { + $(this).val('').removeClass('watermark'); + } + }); + $("#reset").click(function() { + $("#search").val(''); + $("#search").focus(); + }); + $("#search").focus(); + $("#search")[0].setSelectionRange(0, 0); +}); +$.widget("custom.catcomplete", $.ui.autocomplete, { + _create: function() { + this._super(); + this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)"); + }, + _renderMenu: function(ul, items) { + var rMenu = this, + currentCategory = ""; + rMenu.menu.bindings = $(); + $.each(items, function(index, item) { + var li; + if (item.l !== noResult.l && item.category !== currentCategory) { + ul.append("
  • " + item.category + "
  • "); + currentCategory = item.category; + } + li = rMenu._renderItemData(ul, item); + if (item.category) { + li.attr("aria-label", item.category + " : " + item.l); + li.attr("class", "resultItem"); + } else { + li.attr("aria-label", item.l); + li.attr("class", "resultItem"); + } + }); + }, + _renderItem: function(ul, item) { + var label = ""; + if (item.category === catModules) { + label = getHighlightedText(item.l); + } else if (item.category === catPackages) { + label = (item.m) + ? getHighlightedText(item.m + "/" + item.l) + : getHighlightedText(item.l); + } else if (item.category === catTypes) { + label = (item.p) + ? getHighlightedText(item.p + "." + item.l) + : getHighlightedText(item.l); + } else if (item.category === catMembers) { + label = getHighlightedText(item.p + "." + (item.c + "." + item.l)); + } else if (item.category === catSearchTags) { + label = getHighlightedText(item.l); + } else { + label = item.l; + } + var li = $("
  • ").appendTo(ul); + var div = $("
    ").appendTo(li); + if (item.category === catSearchTags) { + if (item.d) { + div.html(label + " (" + item.h + ")
    " + + item.d + "
    "); + } else { + div.html(label + " (" + item.h + ")"); + } + } else { + div.html(label); + } + return li; + } +}); +$(function() { + $("#search").catcomplete({ + minLength: 1, + delay: 100, + source: function(request, response) { + var result = new Array(); + var presult = new Array(); + var tresult = new Array(); + var mresult = new Array(); + var tgresult = new Array(); + var secondaryresult = new Array(); + var displayCount = 0; + var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i"); + camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)"); + var camelCaseMatcher = new RegExp("^" + camelCaseRegexp); + secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); + + // Return the nested innermost name from the specified object + function nestedName(e) { + return e.l.substring(e.l.lastIndexOf(".") + 1); + } + + function concatResults(a1, a2) { + a1 = a1.concat(a2); + a2.length = 0; + return a1; + } + + if (moduleSearchIndex) { + var mdleCount = 0; + $.each(moduleSearchIndex, function(index, item) { + item.category = catModules; + if (exactMatcher.test(item.l)) { + result.push(item); + mdleCount++; + } else if (camelCaseMatcher.test(item.l)) { + result.push(item); + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + displayCount = mdleCount; + result = concatResults(result, secondaryresult); + } + if (packageSearchIndex) { + var pCount = 0; + var pkg = ""; + $.each(packageSearchIndex, function(index, item) { + item.category = catPackages; + pkg = (item.m) + ? (item.m + "/" + item.l) + : item.l; + if (exactMatcher.test(item.l)) { + presult.push(item); + pCount++; + } else if (camelCaseMatcher.test(pkg)) { + presult.push(item); + } else if (secondaryMatcher.test(pkg)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(presult, secondaryresult)); + displayCount = (pCount > displayCount) ? pCount : displayCount; + } + if (typeSearchIndex) { + var tCount = 0; + $.each(typeSearchIndex, function(index, item) { + item.category = catTypes; + var s = nestedName(item); + if (exactMatcher.test(s)) { + tresult.push(item); + tCount++; + } else if (camelCaseMatcher.test(s)) { + tresult.push(item); + } else if (secondaryMatcher.test(item.p + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tresult, secondaryresult)); + displayCount = (tCount > displayCount) ? tCount : displayCount; + } + if (memberSearchIndex) { + var mCount = 0; + $.each(memberSearchIndex, function(index, item) { + item.category = catMembers; + var s = nestedName(item); + if (exactMatcher.test(s)) { + mresult.push(item); + mCount++; + } else if (camelCaseMatcher.test(s)) { + mresult.push(item); + } else if (secondaryMatcher.test(item.c + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(mresult, secondaryresult)); + displayCount = (mCount > displayCount) ? mCount : displayCount; + } + if (tagSearchIndex) { + var tgCount = 0; + $.each(tagSearchIndex, function(index, item) { + item.category = catSearchTags; + if (exactMatcher.test(item.l)) { + tgresult.push(item); + tgCount++; + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tgresult, secondaryresult)); + displayCount = (tgCount > displayCount) ? tgCount : displayCount; + } + displayCount = (displayCount > 500) ? displayCount : 500; + var counter = function() { + var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0}; + var f = function(item) { + count[item.category] += 1; + return (count[item.category] <= displayCount); + }; + return f; + }(); + response(result.filter(counter)); + }, + response: function(event, ui) { + if (!ui.content.length) { + ui.content.push(noResult); + } else { + $("#search").empty(); + } + }, + autoFocus: true, + position: { + collision: "flip" + }, + select: function(event, ui) { + if (ui.item.l !== noResult.l) { + var url = getURLPrefix(ui); + if (ui.item.category === catModules) { + if (useModuleDirectories) { + url += "module-summary.html"; + } else { + url = ui.item.l + "-summary.html"; + } + } else if (ui.item.category === catPackages) { + if (ui.item.url) { + url = ui.item.url; + } else { + url += ui.item.l.replace(/\./g, '/') + "/package-summary.html"; + } + } else if (ui.item.category === catTypes) { + if (ui.item.url) { + url = ui.item.url; + } else if (ui.item.p === "") { + url += ui.item.l + ".html"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; + } + } else if (ui.item.category === catMembers) { + if (ui.item.p === "") { + url += ui.item.c + ".html" + "#"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; + } + if (ui.item.url) { + url += ui.item.url; + } else { + url += ui.item.l; + } + } else if (ui.item.category === catSearchTags) { + url += ui.item.u; + } + if (top !== window) { + parent.classFrame.location = pathtoroot + url; + } else { + window.location.href = pathtoroot + url; + } + $("#search").focus(); + } + } + }); +}); diff --git a/docs/acf-sponge/src-html/co/aikar/commands/ACFSpongeListener.html b/docs/acf-sponge/src-html/co/aikar/commands/ACFSpongeListener.html index d0fa24c7..15b03468 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/ACFSpongeListener.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/ACFSpongeListener.html @@ -1,39 +1,40 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import org.spongepowered.api.entity.living.player.Player;
    -004import org.spongepowered.api.event.Listener;
    -005import org.spongepowered.api.event.Order;
    -006import org.spongepowered.api.event.entity.living.humanoid.player.PlayerChangeClientSettingsEvent;
    -007import org.spongepowered.api.event.filter.cause.First;
    -008import org.spongepowered.api.event.network.ClientConnectionEvent;
    -009
    -010public class ACFSpongeListener {
    -011
    -012    private final SpongeCommandManager manager;
    -013
    -014    public ACFSpongeListener(SpongeCommandManager manager) {
    -015        this.manager = manager;
    -016    }
    -017
    -018    @Listener(order = Order.POST)
    -019    public void onSettingsChange(PlayerChangeClientSettingsEvent changeSettingsEvent, @First Player targetPlayer) {
    -020        //this event will be fired on join as well as every time the player changes it
    -021        manager.setIssuerLocale(targetPlayer, targetPlayer.getLocale());
    -022    }
    -023
    -024    @Listener
    -025    public void onDisconnectCleanup(ClientConnectionEvent.Disconnect disconnectEvent, @First Player player) {
    -026        manager.issuersLocale.remove(player.getUniqueId());
    -027    }
    -028}
    +
    001package co.aikar.commands;
    +002
    +003import org.spongepowered.api.entity.living.player.Player;
    +004import org.spongepowered.api.event.Listener;
    +005import org.spongepowered.api.event.Order;
    +006import org.spongepowered.api.event.entity.living.humanoid.player.PlayerChangeClientSettingsEvent;
    +007import org.spongepowered.api.event.filter.cause.First;
    +008import org.spongepowered.api.event.network.ClientConnectionEvent;
    +009
    +010public class ACFSpongeListener {
    +011
    +012    private final SpongeCommandManager manager;
    +013
    +014    public ACFSpongeListener(SpongeCommandManager manager) {
    +015        this.manager = manager;
    +016    }
    +017
    +018    @Listener(order = Order.POST)
    +019    public void onSettingsChange(PlayerChangeClientSettingsEvent changeSettingsEvent, @First Player targetPlayer) {
    +020        //this event will be fired on join as well as every time the player changes it
    +021        manager.setIssuerLocale(targetPlayer, targetPlayer.getLocale());
    +022    }
    +023
    +024    @Listener
    +025    public void onDisconnectCleanup(ClientConnectionEvent.Disconnect disconnectEvent, @First Player player) {
    +026        manager.issuersLocale.remove(player.getUniqueId());
    +027    }
    +028}
     
     
     
    @@ -96,5 +97,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/ACFSpongeUtil.html b/docs/acf-sponge/src-html/co/aikar/commands/ACFSpongeUtil.html index e23d2ab6..6b8068dc 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/ACFSpongeUtil.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/ACFSpongeUtil.html @@ -1,107 +1,108 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import org.spongepowered.api.Sponge;
    -004import org.spongepowered.api.command.CommandSource;
    -005import org.spongepowered.api.entity.living.player.Player;
    -006
    -007import java.util.ArrayList;
    -008import java.util.Iterator;
    -009import java.util.List;
    -010import java.util.stream.Collectors;
    -011
    -012@SuppressWarnings("WeakerAccess")
    -013public class ACFSpongeUtil {
    -014    public static Player findPlayerSmart(CommandIssuer issuer, String search) {
    -015        CommandSource requester = issuer.getIssuer();
    -016        if (search == null) {
    -017            return null;
    -018        }
    -019        String name = ACFUtil.replace(search, ":confirm", "");
    -020        if (!isValidName(name)) {
    -021            issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
    -022            return null;
    -023        }
    -024
    -025        List<Player> matches = matchPlayer(name);
    -026        List<Player> confirmList = new ArrayList<>();
    -027        findMatches(search, requester, matches, confirmList);
    -028
    -029
    -030        if (matches.size() > 1 || confirmList.size() > 1) {
    -031            String allMatches = matches.stream().map(Player::getName).collect(Collectors.joining(", "));
    -032            issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH,
    -033                    "{search}", name, "{all}", allMatches);
    -034            return null;
    -035        }
    -036
    -037        if (matches.isEmpty()) {
    -038            Player player = ACFUtil.getFirstElement(confirmList);
    -039            if (player == null) {
    -040                issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name);
    -041                return null;
    -042            } else {
    -043
    -044                issuer.sendInfo(MinecraftMessageKeys.PLAYER_IS_VANISHED_CONFIRM, "{vanished}", player.getName());
    -045                return null;
    -046            }
    -047        }
    -048
    -049        return matches.get(0);
    -050    }
    -051
    -052    private static void findMatches(String search, CommandSource requester, List<Player> matches, List<Player> confirmList) {
    -053        // Remove vanished players from smart matching.
    -054        Iterator<Player> iter = matches.iterator();
    -055        //noinspection Duplicates
    -056        while (iter.hasNext()) {
    -057            Player player = iter.next();
    -058            if (requester instanceof Player && !((Player) requester).canSee(player)) {
    -059                if (requester.hasPermission("acf.seevanish")) {
    -060                    if (!search.endsWith(":confirm")) {
    -061                        confirmList.add(player);
    -062                        iter.remove();
    -063                    }
    -064                } else {
    -065                    iter.remove();
    -066                }
    -067            }
    -068        }
    -069    }
    -070
    -071    public static List<Player> matchPlayer(String partialName) {
    -072        List<Player> matchedPlayers = new ArrayList<>();
    -073
    -074        for (Player iterPlayer : Sponge.getServer().getOnlinePlayers()) {
    -075            String iterPlayerName = iterPlayer.getName();
    -076
    -077            if (partialName.equalsIgnoreCase(iterPlayerName)) {
    -078                // Exact match
    -079                matchedPlayers.clear();
    -080                matchedPlayers.add(iterPlayer);
    -081                break;
    -082            }
    -083            if (iterPlayerName.toLowerCase(java.util.Locale.ENGLISH).contains(partialName.toLowerCase(java.util.Locale.ENGLISH))) {
    -084                // Partial match
    -085                matchedPlayers.add(iterPlayer);
    -086            }
    -087        }
    -088
    -089        return matchedPlayers;
    -090    }
    -091
    -092    public static boolean isValidName(String name) {
    -093        return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches();
    -094    }
    -095
    -096}
    +
    001package co.aikar.commands;
    +002
    +003import org.spongepowered.api.Sponge;
    +004import org.spongepowered.api.command.CommandSource;
    +005import org.spongepowered.api.entity.living.player.Player;
    +006
    +007import java.util.ArrayList;
    +008import java.util.Iterator;
    +009import java.util.List;
    +010import java.util.stream.Collectors;
    +011
    +012@SuppressWarnings("WeakerAccess")
    +013public class ACFSpongeUtil {
    +014    public static Player findPlayerSmart(CommandIssuer issuer, String search) {
    +015        CommandSource requester = issuer.getIssuer();
    +016        if (search == null) {
    +017            return null;
    +018        }
    +019        String name = ACFUtil.replace(search, ":confirm", "");
    +020        if (!isValidName(name)) {
    +021            issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
    +022            return null;
    +023        }
    +024
    +025        List<Player> matches = matchPlayer(name);
    +026        List<Player> confirmList = new ArrayList<>();
    +027        findMatches(search, requester, matches, confirmList);
    +028
    +029
    +030        if (matches.size() > 1 || confirmList.size() > 1) {
    +031            String allMatches = matches.stream().map(Player::getName).collect(Collectors.joining(", "));
    +032            issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH,
    +033                    "{search}", name, "{all}", allMatches);
    +034            return null;
    +035        }
    +036
    +037        if (matches.isEmpty()) {
    +038            Player player = ACFUtil.getFirstElement(confirmList);
    +039            if (player == null) {
    +040                issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name);
    +041                return null;
    +042            } else {
    +043
    +044                issuer.sendInfo(MinecraftMessageKeys.PLAYER_IS_VANISHED_CONFIRM, "{vanished}", player.getName());
    +045                return null;
    +046            }
    +047        }
    +048
    +049        return matches.get(0);
    +050    }
    +051
    +052    private static void findMatches(String search, CommandSource requester, List<Player> matches, List<Player> confirmList) {
    +053        // Remove vanished players from smart matching.
    +054        Iterator<Player> iter = matches.iterator();
    +055        //noinspection Duplicates
    +056        while (iter.hasNext()) {
    +057            Player player = iter.next();
    +058            if (requester instanceof Player && !((Player) requester).canSee(player)) {
    +059                if (requester.hasPermission("acf.seevanish")) {
    +060                    if (!search.endsWith(":confirm")) {
    +061                        confirmList.add(player);
    +062                        iter.remove();
    +063                    }
    +064                } else {
    +065                    iter.remove();
    +066                }
    +067            }
    +068        }
    +069    }
    +070
    +071    public static List<Player> matchPlayer(String partialName) {
    +072        List<Player> matchedPlayers = new ArrayList<>();
    +073
    +074        for (Player iterPlayer : Sponge.getServer().getOnlinePlayers()) {
    +075            String iterPlayerName = iterPlayer.getName();
    +076
    +077            if (partialName.equalsIgnoreCase(iterPlayerName)) {
    +078                // Exact match
    +079                matchedPlayers.clear();
    +080                matchedPlayers.add(iterPlayer);
    +081                break;
    +082            }
    +083            if (iterPlayerName.toLowerCase(java.util.Locale.ENGLISH).contains(partialName.toLowerCase(java.util.Locale.ENGLISH))) {
    +084                // Partial match
    +085                matchedPlayers.add(iterPlayer);
    +086            }
    +087        }
    +088
    +089        return matchedPlayers;
    +090    }
    +091
    +092    public static boolean isValidName(String name) {
    +093        return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches();
    +094    }
    +095
    +096}
     
     
     
    @@ -164,5 +165,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/MinecraftMessageKeys.html b/docs/acf-sponge/src-html/co/aikar/commands/MinecraftMessageKeys.html index 5c953123..72b31cf1 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/MinecraftMessageKeys.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/MinecraftMessageKeys.html @@ -1,55 +1,58 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.locales.MessageKey;
    -027import co.aikar.locales.MessageKeyProvider;
    -028
    -029public enum MinecraftMessageKeys implements MessageKeyProvider {
    -030    INVALID_WORLD,
    -031    YOU_MUST_BE_HOLDING_ITEM,
    -032    PLAYER_IS_VANISHED_CONFIRM,
    -033    USERNAME_TOO_SHORT,
    -034    IS_NOT_A_VALID_NAME,
    -035    MULTIPLE_PLAYERS_MATCH,
    -036    NO_PLAYER_FOUND_SERVER,
    -037    NO_PLAYER_FOUND
    -038    ;
    -039
    -040    private final MessageKey key = MessageKey.of("acf-minecraft." + this.name().toLowerCase());
    -041    public MessageKey getMessageKey() {
    -042        return key;
    -043    }
    -044}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.locales.MessageKey;
    +027import co.aikar.locales.MessageKeyProvider;
    +028
    +029import java.util.Locale;
    +030
    +031public enum MinecraftMessageKeys implements MessageKeyProvider {
    +032    INVALID_WORLD,
    +033    YOU_MUST_BE_HOLDING_ITEM,
    +034    PLAYER_IS_VANISHED_CONFIRM,
    +035    USERNAME_TOO_SHORT,
    +036    IS_NOT_A_VALID_NAME,
    +037    MULTIPLE_PLAYERS_MATCH,
    +038    NO_PLAYER_FOUND_SERVER,
    +039    NO_PLAYER_FOUND
    +040    ;
    +041
    +042    private final MessageKey key = MessageKey.of("acf-minecraft." + this.name().toLowerCase(Locale.ENGLISH));
    +043    public MessageKey getMessageKey() {
    +044        return key;
    +045    }
    +046}
     
     
     
    @@ -112,5 +115,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandCompletionContext.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandCompletionContext.html index b6e54e1e..cd3e3383 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandCompletionContext.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandCompletionContext.html @@ -1,54 +1,55 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.spongepowered.api.command.CommandSource;
    -027import org.spongepowered.api.entity.living.player.Player;
    -028
    -029@SuppressWarnings("WeakerAccess")
    -030public class SpongeCommandCompletionContext extends CommandCompletionContext<SpongeCommandIssuer> {
    -031
    -032    SpongeCommandCompletionContext(final RegisteredCommand command, final SpongeCommandIssuer issuer, final String input, final String config, final String[] args) {
    -033        super(command, issuer, input, config, args);
    -034    }
    -035
    -036    public CommandSource getSource() {
    -037        return this.issuer.getIssuer();
    -038    }
    -039
    -040    public Player getPlayer() {
    -041        return this.issuer.getPlayer();
    -042    }
    -043}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.spongepowered.api.command.CommandSource;
    +027import org.spongepowered.api.entity.living.player.Player;
    +028
    +029@SuppressWarnings("WeakerAccess")
    +030public class SpongeCommandCompletionContext extends CommandCompletionContext<SpongeCommandIssuer> {
    +031
    +032    SpongeCommandCompletionContext(final RegisteredCommand command, final SpongeCommandIssuer issuer, final String input, final String config, final String[] args) {
    +033        super(command, issuer, input, config, args);
    +034    }
    +035
    +036    public CommandSource getSource() {
    +037        return this.issuer.getIssuer();
    +038    }
    +039
    +040    public Player getPlayer() {
    +041        return this.issuer.getPlayer();
    +042    }
    +043}
     
     
     
    @@ -111,5 +112,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandCompletions.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandCompletions.html index 771c57d9..5eb2b6ae 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandCompletions.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandCompletions.html @@ -1,43 +1,44 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026@SuppressWarnings("WeakerAccess")
    -027public class SpongeCommandCompletions extends CommandCompletions<SpongeCommandCompletionContext> {
    -028
    -029    public SpongeCommandCompletions(final SpongeCommandManager manager) {
    -030        super(manager);
    -031    }
    -032}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026@SuppressWarnings("WeakerAccess")
    +027public class SpongeCommandCompletions extends CommandCompletions<SpongeCommandCompletionContext> {
    +028
    +029    public SpongeCommandCompletions(final SpongeCommandManager manager) {
    +030        super(manager);
    +031    }
    +032}
     
     
     
    @@ -100,5 +101,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandContexts.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandContexts.html index 9f19bbbb..c328443d 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandContexts.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandContexts.html @@ -1,189 +1,190 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.commands.contexts.CommandResultSupplier;
    -027import co.aikar.commands.sponge.contexts.OnlinePlayer;
    -028import org.jetbrains.annotations.Nullable;
    -029import org.spongepowered.api.Sponge;
    -030import org.spongepowered.api.command.CommandSource;
    -031import org.spongepowered.api.entity.living.player.Player;
    -032import org.spongepowered.api.entity.living.player.User;
    -033import org.spongepowered.api.service.user.UserStorageService;
    -034import org.spongepowered.api.text.format.TextColor;
    -035import org.spongepowered.api.text.format.TextStyle;
    -036import org.spongepowered.api.world.World;
    -037
    -038import java.util.HashSet;
    -039import java.util.Optional;
    -040import java.util.Set;
    -041import java.util.regex.Pattern;
    -042import java.util.stream.Collectors;
    -043import java.util.stream.Stream;
    -044
    -045@SuppressWarnings("WeakerAccess")
    -046public class SpongeCommandContexts extends CommandContexts<SpongeCommandExecutionContext> {
    -047
    -048    public SpongeCommandContexts(final SpongeCommandManager manager) {
    -049        super(manager);
    -050
    -051        registerIssuerOnlyContext(CommandResultSupplier.class, c -> new CommandResultSupplier());
    -052        registerContext(OnlinePlayer.class, c -> getOnlinePlayer(c.getIssuer(), c.popFirstArg(), c.isOptional()));
    -053        registerContext(co.aikar.commands.contexts.OnlinePlayer.class, c -> {
    -054            OnlinePlayer onlinePlayer = getOnlinePlayer(c.getIssuer(), c.popFirstArg(), c.isOptional());
    -055            return onlinePlayer != null ? new co.aikar.commands.contexts.OnlinePlayer(onlinePlayer.getPlayer()) : null;
    -056        });
    -057        registerContext(User.class, c -> {
    -058            String name = c.popFirstArg();
    -059            // try online players first
    -060            Optional<Player> targetPlayer = Sponge.getGame().getServer().getPlayer(name);
    -061            if (targetPlayer.isPresent()) {
    -062                return targetPlayer.get();
    -063            }
    -064
    -065            Optional<UserStorageService> service = Sponge.getGame().getServiceManager().provide(UserStorageService.class);
    -066            if (!service.isPresent()) {
    -067                manager.log(LogLevel.ERROR, "No UserStorageService is available", new Error());
    -068                throw new InvalidCommandArgument(MessageKeys.ERROR_GENERIC_LOGGED, false);
    -069            }
    -070            Optional<User> user = service.get().get(name);
    -071            if (user.isPresent()) {
    -072                return user.get();
    -073            }
    -074            if (!c.isOptional()) {
    -075                throw new InvalidCommandArgument(MinecraftMessageKeys.NO_PLAYER_FOUND, false, "{search}", name);
    -076            }
    -077
    -078            return null;
    -079        });
    -080        registerContext(TextColor.class, c -> {
    -081            String first = c.popFirstArg();
    -082            Stream<TextColor> colours = Sponge.getRegistry().getAllOf(TextColor.class).stream();
    -083            String filter = c.getFlagValue("filter", (String) null);
    -084            if (filter != null) {
    -085                filter = ACFUtil.simplifyString(filter);
    -086                String finalFilter = filter;
    -087                colours = colours.filter(colour -> finalFilter.equals(ACFUtil.simplifyString(colour.getName())));
    -088            }
    -089            Stream<TextColor> finalColours = colours;
    -090            return Sponge.getRegistry().getType(TextColor.class, ACFUtil.simplifyString(first)).orElseThrow(() -> {
    -091                String valid = finalColours
    -092                        .map(colour -> "<c2>" + ACFUtil.simplifyString(colour.getName()) + "</c2>")
    -093                        .collect(Collectors.joining("<c1>,</c1> "));
    -094                return new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
    -095            });
    -096        });
    -097        registerContext(TextStyle.Base.class, c -> {
    -098            String first = c.popFirstArg();
    -099            Stream<TextStyle.Base> styles = Sponge.getRegistry().getAllOf(TextStyle.Base.class).stream();
    -100            String filter = c.getFlagValue("filter", (String) null);
    -101            if (filter != null) {
    -102                filter = ACFUtil.simplifyString(filter);
    -103                String finalFilter = filter;
    -104                styles = styles.filter(style -> finalFilter.equals(ACFUtil.simplifyString(style.getName())));
    -105            }
    -106            Stream<TextStyle.Base> finalStyles = styles;
    -107            return Sponge.getRegistry().getType(TextStyle.Base.class, ACFUtil.simplifyString(first)).orElseThrow(() -> {
    -108                String valid = finalStyles
    -109                        .map(style -> "<c2>" + ACFUtil.simplifyString(style.getName()) + "</c2>")
    -110                        .collect(Collectors.joining("<c1>,</c1> "));
    -111                return new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
    -112            });
    -113        });
    -114
    -115        registerIssuerAwareContext(CommandSource.class, SpongeCommandExecutionContext::getSource);
    -116        registerIssuerAwareContext(Player.class, (c) -> {
    -117            Player player = c.getSource() instanceof Player ? (Player) c.getSource() : null;
    -118            if (player == null && !c.isOptional()) {
    -119                throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
    -120            }
    -121            /*PlayerInventory inventory = player != null ? player.getInventory() : null;
    -122            if (inventory != null && c.hasFlag("itemheld") && !ACFBukkitUtil.isValidItem(inventory.getItem(inventory.getHeldItemSlot()))) {
    -123                throw new InvalidCommandArgument(MinecraftMessageKeys.YOU_MUST_BE_HOLDING_ITEM, false);
    -124            }*/
    -125            return player;
    -126        });
    -127        registerContext(OnlinePlayer[].class, (c) -> {
    -128            SpongeCommandIssuer issuer = c.getIssuer();
    -129            final String search = c.popFirstArg();
    -130            boolean allowMissing = c.hasFlag("allowmissing");
    -131            Set<OnlinePlayer> players = new HashSet<>();
    -132            Pattern split = ACFPatterns.COMMA;
    -133            String splitter = c.getFlagValue("splitter", (String) null);
    -134            if (splitter != null) {
    -135                split = Pattern.compile(Pattern.quote(splitter));
    -136            }
    -137            for (String lookup : split.split(search)) {
    -138                OnlinePlayer player = getOnlinePlayer(issuer, lookup, allowMissing);
    -139                if (player != null) {
    -140                    players.add(player);
    -141                }
    -142            }
    -143            if (players.isEmpty() && !c.hasFlag("allowempty")) {
    -144                issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER,
    -145                        "{search}", search);
    -146
    -147                throw new InvalidCommandArgument(false);
    -148            }
    -149            return players.toArray(new OnlinePlayer[players.size()]);
    -150        });
    -151        registerIssuerAwareContext(World.class, (c) -> {
    -152            String firstArg = c.getFirstArg();
    -153            java.util.Optional<World> world = firstArg != null ? Sponge.getServer().getWorld(firstArg) : java.util.Optional.empty();
    -154            if (world.isPresent()) {
    -155                c.popFirstArg();
    -156            }
    -157            if (!world.isPresent() && c.getSource() instanceof Player) {
    -158                world = java.util.Optional.of(((Player) c.getSource()).getWorld());
    -159            }
    -160            if (!world.isPresent()) {
    -161                throw new InvalidCommandArgument(MinecraftMessageKeys.INVALID_WORLD);
    -162            }
    -163            return world.get();
    -164        });
    -165    }
    -166
    -167    @Nullable
    -168    OnlinePlayer getOnlinePlayer(SpongeCommandIssuer issuer, String lookup, boolean allowMissing) throws InvalidCommandArgument {
    -169        Player player = ACFSpongeUtil.findPlayerSmart(issuer, lookup);
    -170        if (player == null) {
    -171            if (allowMissing) {
    -172                return null;
    -173            }
    -174            throw new InvalidCommandArgument(false);
    -175        }
    -176        return new OnlinePlayer(player);
    -177    }
    -178}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.commands.contexts.CommandResultSupplier;
    +027import co.aikar.commands.sponge.contexts.OnlinePlayer;
    +028import org.jetbrains.annotations.Nullable;
    +029import org.spongepowered.api.Sponge;
    +030import org.spongepowered.api.command.CommandSource;
    +031import org.spongepowered.api.entity.living.player.Player;
    +032import org.spongepowered.api.entity.living.player.User;
    +033import org.spongepowered.api.service.user.UserStorageService;
    +034import org.spongepowered.api.text.format.TextColor;
    +035import org.spongepowered.api.text.format.TextStyle;
    +036import org.spongepowered.api.world.World;
    +037
    +038import java.util.HashSet;
    +039import java.util.Optional;
    +040import java.util.Set;
    +041import java.util.regex.Pattern;
    +042import java.util.stream.Collectors;
    +043import java.util.stream.Stream;
    +044
    +045@SuppressWarnings("WeakerAccess")
    +046public class SpongeCommandContexts extends CommandContexts<SpongeCommandExecutionContext> {
    +047
    +048    public SpongeCommandContexts(final SpongeCommandManager manager) {
    +049        super(manager);
    +050
    +051        registerIssuerOnlyContext(CommandResultSupplier.class, c -> new CommandResultSupplier());
    +052        registerContext(OnlinePlayer.class, c -> getOnlinePlayer(c.getIssuer(), c.popFirstArg(), c.isOptional()));
    +053        registerContext(co.aikar.commands.contexts.OnlinePlayer.class, c -> {
    +054            OnlinePlayer onlinePlayer = getOnlinePlayer(c.getIssuer(), c.popFirstArg(), c.isOptional());
    +055            return onlinePlayer != null ? new co.aikar.commands.contexts.OnlinePlayer(onlinePlayer.getPlayer()) : null;
    +056        });
    +057        registerContext(User.class, c -> {
    +058            String name = c.popFirstArg();
    +059            // try online players first
    +060            Optional<Player> targetPlayer = Sponge.getGame().getServer().getPlayer(name);
    +061            if (targetPlayer.isPresent()) {
    +062                return targetPlayer.get();
    +063            }
    +064
    +065            Optional<UserStorageService> service = Sponge.getGame().getServiceManager().provide(UserStorageService.class);
    +066            if (!service.isPresent()) {
    +067                manager.log(LogLevel.ERROR, "No UserStorageService is available", new Error());
    +068                throw new InvalidCommandArgument(MessageKeys.ERROR_GENERIC_LOGGED, false);
    +069            }
    +070            Optional<User> user = service.get().get(name);
    +071            if (user.isPresent()) {
    +072                return user.get();
    +073            }
    +074            if (!c.isOptional()) {
    +075                throw new InvalidCommandArgument(MinecraftMessageKeys.NO_PLAYER_FOUND, false, "{search}", name);
    +076            }
    +077
    +078            return null;
    +079        });
    +080        registerContext(TextColor.class, c -> {
    +081            String first = c.popFirstArg();
    +082            Stream<TextColor> colours = Sponge.getRegistry().getAllOf(TextColor.class).stream();
    +083            String filter = c.getFlagValue("filter", (String) null);
    +084            if (filter != null) {
    +085                filter = ACFUtil.simplifyString(filter);
    +086                String finalFilter = filter;
    +087                colours = colours.filter(colour -> finalFilter.equals(ACFUtil.simplifyString(colour.getName())));
    +088            }
    +089            Stream<TextColor> finalColours = colours;
    +090            return Sponge.getRegistry().getType(TextColor.class, ACFUtil.simplifyString(first)).orElseThrow(() -> {
    +091                String valid = finalColours
    +092                        .map(colour -> "<c2>" + ACFUtil.simplifyString(colour.getName()) + "</c2>")
    +093                        .collect(Collectors.joining("<c1>,</c1> "));
    +094                return new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
    +095            });
    +096        });
    +097        registerContext(TextStyle.Base.class, c -> {
    +098            String first = c.popFirstArg();
    +099            Stream<TextStyle.Base> styles = Sponge.getRegistry().getAllOf(TextStyle.Base.class).stream();
    +100            String filter = c.getFlagValue("filter", (String) null);
    +101            if (filter != null) {
    +102                filter = ACFUtil.simplifyString(filter);
    +103                String finalFilter = filter;
    +104                styles = styles.filter(style -> finalFilter.equals(ACFUtil.simplifyString(style.getName())));
    +105            }
    +106            Stream<TextStyle.Base> finalStyles = styles;
    +107            return Sponge.getRegistry().getType(TextStyle.Base.class, ACFUtil.simplifyString(first)).orElseThrow(() -> {
    +108                String valid = finalStyles
    +109                        .map(style -> "<c2>" + ACFUtil.simplifyString(style.getName()) + "</c2>")
    +110                        .collect(Collectors.joining("<c1>,</c1> "));
    +111                return new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
    +112            });
    +113        });
    +114
    +115        registerIssuerAwareContext(CommandSource.class, SpongeCommandExecutionContext::getSource);
    +116        registerIssuerAwareContext(Player.class, (c) -> {
    +117            Player player = c.getSource() instanceof Player ? (Player) c.getSource() : null;
    +118            if (player == null && !c.isOptional()) {
    +119                throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
    +120            }
    +121            /*PlayerInventory inventory = player != null ? player.getInventory() : null;
    +122            if (inventory != null && c.hasFlag("itemheld") && !ACFBukkitUtil.isValidItem(inventory.getItem(inventory.getHeldItemSlot()))) {
    +123                throw new InvalidCommandArgument(MinecraftMessageKeys.YOU_MUST_BE_HOLDING_ITEM, false);
    +124            }*/
    +125            return player;
    +126        });
    +127        registerContext(OnlinePlayer[].class, (c) -> {
    +128            SpongeCommandIssuer issuer = c.getIssuer();
    +129            final String search = c.popFirstArg();
    +130            boolean allowMissing = c.hasFlag("allowmissing");
    +131            Set<OnlinePlayer> players = new HashSet<>();
    +132            Pattern split = ACFPatterns.COMMA;
    +133            String splitter = c.getFlagValue("splitter", (String) null);
    +134            if (splitter != null) {
    +135                split = Pattern.compile(Pattern.quote(splitter));
    +136            }
    +137            for (String lookup : split.split(search)) {
    +138                OnlinePlayer player = getOnlinePlayer(issuer, lookup, allowMissing);
    +139                if (player != null) {
    +140                    players.add(player);
    +141                }
    +142            }
    +143            if (players.isEmpty() && !c.hasFlag("allowempty")) {
    +144                issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER,
    +145                        "{search}", search);
    +146
    +147                throw new InvalidCommandArgument(false);
    +148            }
    +149            return players.toArray(new OnlinePlayer[players.size()]);
    +150        });
    +151        registerIssuerAwareContext(World.class, (c) -> {
    +152            String firstArg = c.getFirstArg();
    +153            java.util.Optional<World> world = firstArg != null ? Sponge.getServer().getWorld(firstArg) : java.util.Optional.empty();
    +154            if (world.isPresent()) {
    +155                c.popFirstArg();
    +156            }
    +157            if (!world.isPresent() && c.getSource() instanceof Player) {
    +158                world = java.util.Optional.of(((Player) c.getSource()).getWorld());
    +159            }
    +160            if (!world.isPresent()) {
    +161                throw new InvalidCommandArgument(MinecraftMessageKeys.INVALID_WORLD);
    +162            }
    +163            return world.get();
    +164        });
    +165    }
    +166
    +167    @Nullable
    +168    OnlinePlayer getOnlinePlayer(SpongeCommandIssuer issuer, String lookup, boolean allowMissing) throws InvalidCommandArgument {
    +169        Player player = ACFSpongeUtil.findPlayerSmart(issuer, lookup);
    +170        if (player == null) {
    +171            if (allowMissing) {
    +172                return null;
    +173            }
    +174            throw new InvalidCommandArgument(false);
    +175        }
    +176        return new OnlinePlayer(player);
    +177    }
    +178}
     
     
     
    @@ -246,5 +247,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandExecutionContext.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandExecutionContext.html index 01e43da3..ddc23c2d 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandExecutionContext.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandExecutionContext.html @@ -1,57 +1,58 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.spongepowered.api.command.CommandSource;
    -027import org.spongepowered.api.entity.living.player.Player;
    -028
    -029import java.util.List;
    -030import java.util.Map;
    -031
    -032public class SpongeCommandExecutionContext extends CommandExecutionContext<SpongeCommandExecutionContext, SpongeCommandIssuer> {
    -033
    -034    SpongeCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, SpongeCommandIssuer sender, List<String> args,
    -035                                  int index, Map<String, Object> passedArgs) {
    -036        super(cmd, param, sender, args, index, passedArgs);
    -037    }
    -038
    -039    public CommandSource getSource() {
    -040        return this.issuer.getIssuer();
    -041    }
    -042
    -043    public Player getPlayer() {
    -044        return this.issuer.getPlayer();
    -045    }
    -046}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.spongepowered.api.command.CommandSource;
    +027import org.spongepowered.api.entity.living.player.Player;
    +028
    +029import java.util.List;
    +030import java.util.Map;
    +031
    +032public class SpongeCommandExecutionContext extends CommandExecutionContext<SpongeCommandExecutionContext, SpongeCommandIssuer> {
    +033
    +034    SpongeCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, SpongeCommandIssuer sender, List<String> args,
    +035                                  int index, Map<String, Object> passedArgs) {
    +036        super(cmd, param, sender, args, index, passedArgs);
    +037    }
    +038
    +039    public CommandSource getSource() {
    +040        return this.issuer.getIssuer();
    +041    }
    +042
    +043    public Player getPlayer() {
    +044        return this.issuer.getPlayer();
    +045    }
    +046}
     
     
     
    @@ -114,5 +115,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandIssuer.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandIssuer.html index ed762102..b27cb672 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandIssuer.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandIssuer.html @@ -1,108 +1,109 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import org.jetbrains.annotations.NotNull;
    -027import org.spongepowered.api.command.CommandSource;
    -028import org.spongepowered.api.entity.living.player.Player;
    -029import org.spongepowered.api.text.serializer.TextSerializers;
    -030import org.spongepowered.api.util.Identifiable;
    -031
    -032import java.nio.charset.StandardCharsets;
    -033import java.util.Objects;
    -034import java.util.UUID;
    -035
    -036public class SpongeCommandIssuer implements CommandIssuer {
    -037
    -038    private final SpongeCommandManager manager;
    -039    private final CommandSource source;
    -040
    -041    SpongeCommandIssuer(SpongeCommandManager manager, final CommandSource source) {
    -042        this.manager = manager;
    -043        this.source = source;
    -044    }
    -045
    -046    @Override
    -047    public boolean isPlayer() {
    -048        return this.source instanceof Player;
    -049    }
    -050
    -051    @Override
    -052    public CommandSource getIssuer() {
    -053        return this.source;
    -054    }
    -055
    -056    @Override
    -057    public @NotNull UUID getUniqueId() {
    -058        if (this.source instanceof Identifiable) {
    -059            return ((Identifiable) source).getUniqueId();
    -060        }
    -061
    -062        //generate a unique id based of the name (like for the console command sender)
    -063        return UUID.nameUUIDFromBytes(source.getName().getBytes(StandardCharsets.UTF_8));
    -064    }
    -065
    -066    public Player getPlayer() {
    -067        return isPlayer() ? (Player) source : null;
    -068    }
    -069
    -070    @Override
    -071    public CommandManager getManager() {
    -072        return manager;
    -073    }
    -074
    -075    @Override
    -076    public void sendMessageInternal(String message) {
    -077        this.source.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(message));
    -078    }
    -079
    -080    @Override
    -081    public boolean hasPermission(final String permission) {
    -082        return this.source.hasPermission(permission);
    -083    }
    -084
    -085    @Override
    -086    public boolean equals(Object o) {
    -087        if (this == o) return true;
    -088        if (o == null || getClass() != o.getClass()) return false;
    -089        SpongeCommandIssuer that = (SpongeCommandIssuer) o;
    -090        return Objects.equals(source, that.source);
    -091    }
    -092
    -093    @Override
    -094    public int hashCode() {
    -095        return Objects.hash(source);
    -096    }
    -097}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import org.jetbrains.annotations.NotNull;
    +027import org.spongepowered.api.command.CommandSource;
    +028import org.spongepowered.api.entity.living.player.Player;
    +029import org.spongepowered.api.text.serializer.TextSerializers;
    +030import org.spongepowered.api.util.Identifiable;
    +031
    +032import java.nio.charset.StandardCharsets;
    +033import java.util.Objects;
    +034import java.util.UUID;
    +035
    +036public class SpongeCommandIssuer implements CommandIssuer {
    +037
    +038    private final SpongeCommandManager manager;
    +039    private final CommandSource source;
    +040
    +041    SpongeCommandIssuer(SpongeCommandManager manager, final CommandSource source) {
    +042        this.manager = manager;
    +043        this.source = source;
    +044    }
    +045
    +046    @Override
    +047    public boolean isPlayer() {
    +048        return this.source instanceof Player;
    +049    }
    +050
    +051    @Override
    +052    public CommandSource getIssuer() {
    +053        return this.source;
    +054    }
    +055
    +056    @Override
    +057    public @NotNull UUID getUniqueId() {
    +058        if (this.source instanceof Identifiable) {
    +059            return ((Identifiable) source).getUniqueId();
    +060        }
    +061
    +062        //generate a unique id based of the name (like for the console command sender)
    +063        return UUID.nameUUIDFromBytes(source.getName().getBytes(StandardCharsets.UTF_8));
    +064    }
    +065
    +066    public Player getPlayer() {
    +067        return isPlayer() ? (Player) source : null;
    +068    }
    +069
    +070    @Override
    +071    public CommandManager getManager() {
    +072        return manager;
    +073    }
    +074
    +075    @Override
    +076    public void sendMessageInternal(String message) {
    +077        this.source.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(message));
    +078    }
    +079
    +080    @Override
    +081    public boolean hasPermission(final String permission) {
    +082        return this.source.hasPermission(permission);
    +083    }
    +084
    +085    @Override
    +086    public boolean equals(Object o) {
    +087        if (this == o) return true;
    +088        if (o == null || getClass() != o.getClass()) return false;
    +089        SpongeCommandIssuer that = (SpongeCommandIssuer) o;
    +090        return Objects.equals(source, that.source);
    +091    }
    +092
    +093    @Override
    +094    public int hashCode() {
    +095        return Objects.hash(source);
    +096    }
    +097}
     
     
     
    @@ -165,5 +166,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandManager.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandManager.html index c4b31743..31404dc7 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandManager.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandManager.html @@ -1,223 +1,225 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    -027import co.aikar.timings.Timing;
    -028import co.aikar.timings.Timings;
    -029import org.slf4j.Logger;
    -030import org.spongepowered.api.Sponge;
    -031import org.spongepowered.api.command.CommandSource;
    -032import org.spongepowered.api.plugin.PluginContainer;
    -033import org.spongepowered.api.text.format.TextColor;
    -034import org.spongepowered.api.text.format.TextColors;
    -035
    -036import java.lang.reflect.Method;
    -037import java.util.Collection;
    -038import java.util.Collections;
    -039import java.util.HashMap;
    -040import java.util.List;
    -041import java.util.Map;
    -042
    -043@SuppressWarnings("WeakerAccess")
    -044public class SpongeCommandManager extends CommandManager<
    -045        CommandSource,
    -046        SpongeCommandIssuer,
    -047        TextColor,
    -048        SpongeMessageFormatter,
    -049        SpongeCommandExecutionContext,
    -050        SpongeConditionContext
    -051    > {
    -052
    -053    protected final PluginContainer plugin;
    -054    protected Map<String, SpongeRootCommand> registeredCommands = new HashMap<>();
    -055    protected SpongeCommandContexts contexts;
    -056    protected SpongeCommandCompletions completions;
    -057    private Timing commandTiming;
    -058    protected SpongeLocales locales;
    -059
    -060    public SpongeCommandManager(PluginContainer plugin) {
    -061        this.plugin = plugin;
    -062        String pluginName = "acf-" + plugin.getName();
    -063        getLocales().addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
    -064        this.commandTiming = Timings.of(plugin, "Commands");
    -065
    -066        this.formatters.put(MessageType.ERROR, defaultFormatter = new SpongeMessageFormatter(TextColors.RED, TextColors.YELLOW, TextColors.RED));
    -067        this.formatters.put(MessageType.SYNTAX, new SpongeMessageFormatter(TextColors.YELLOW, TextColors.GREEN, TextColors.WHITE));
    -068        this.formatters.put(MessageType.INFO, new SpongeMessageFormatter(TextColors.BLUE, TextColors.DARK_GREEN, TextColors.GREEN));
    -069        this.formatters.put(MessageType.HELP, new SpongeMessageFormatter(TextColors.AQUA, TextColors.GREEN, TextColors.YELLOW));
    -070        getLocales(); // auto load locales
    -071
    -072        Sponge.getEventManager().registerListeners(plugin, new ACFSpongeListener(this));
    -073
    -074        //TODO more default dependencies for sponge
    -075        registerDependency(plugin.getClass(), plugin);
    -076    }
    -077
    -078    public PluginContainer getPlugin() {
    -079        return plugin;
    -080    }
    -081
    -082    @Override
    -083    public boolean isCommandIssuer(Class<?> type) {
    -084        return CommandSource.class.isAssignableFrom(type);
    -085    }
    -086
    -087    @Override
    -088    public synchronized CommandContexts<SpongeCommandExecutionContext> getCommandContexts() {
    -089        if (this.contexts == null) {
    -090            this.contexts = new SpongeCommandContexts(this);
    -091        }
    -092        return contexts;
    -093    }
    -094
    -095    @Override
    -096    public synchronized CommandCompletions<SpongeCommandCompletionContext> getCommandCompletions() {
    -097        if (this.completions == null) {
    -098            this.completions = new SpongeCommandCompletions(this);
    -099        }
    -100        return completions;
    -101    }
    -102
    -103    @Override
    -104    public SpongeLocales getLocales() {
    -105        if (this.locales == null) {
    -106            this.locales = new SpongeLocales(this);
    -107            this.locales.loadLanguages();
    -108        }
    -109        return locales;
    -110    }
    -111
    -112    @Override
    -113    public boolean hasRegisteredCommands() {
    -114        return !registeredCommands.isEmpty();
    -115    }
    -116
    -117    @Override
    -118    public void registerCommand(BaseCommand command) {
    -119        command.onRegister(this);
    -120
    -121        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    -122            String commandName = entry.getKey().toLowerCase();
    -123            SpongeRootCommand spongeCommand = (SpongeRootCommand) entry.getValue();
    -124            if (!spongeCommand.isRegistered) {
    -125                Sponge.getCommandManager().register(this.plugin, spongeCommand, commandName);
    -126            }
    -127            spongeCommand.isRegistered = true;
    -128            registeredCommands.put(commandName, spongeCommand);
    -129        }
    -130    }
    -131
    -132    public Timing createTiming(final String name) {
    -133        return Timings.of(this.plugin, name, this.commandTiming);
    -134    }
    -135
    -136    @Override
    -137    public RootCommand createRootCommand(String cmd) {
    -138        return new SpongeRootCommand(this, cmd);
    -139    }
    -140    
    -141    @Override
    -142    public Collection<RootCommand> getRegisteredRootCommands() {
    -143        return Collections.unmodifiableCollection(registeredCommands.values());
    -144    }
    -145
    -146    @Override
    -147    public SpongeCommandIssuer getCommandIssuer(Object issuer) {
    -148        if (!(issuer instanceof CommandSource)) {
    -149            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
    -150        }
    -151        return new SpongeCommandIssuer(this, (CommandSource) issuer);
    -152    }
    -153
    -154    @Override
    -155    public SpongeCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
    -156        return new SpongeCommandExecutionContext(command, parameter, (SpongeCommandIssuer) sender, args, i, passedArgs);
    -157    }
    -158
    -159    @Override
    -160    public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
    -161        return new SpongeCommandCompletionContext(command, (SpongeCommandIssuer) sender, input, config, args);
    -162    }
    -163
    -164    @Override
    -165    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
    -166        return new SpongeRegisteredCommand(command, cmdName, method, prefSubCommand);
    -167    }
    -168
    -169    @Override
    -170    public void log(final LogLevel level, final String message, final Throwable throwable) {
    -171        Logger logger = this.plugin.getLogger();
    -172        switch(level) {
    -173            case INFO:
    -174                logger.info(LogLevel.LOG_PREFIX + message);
    -175                if (throwable != null) {
    -176                    for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    -177                        logger.info(LogLevel.LOG_PREFIX + line);
    -178                    }
    -179                }
    -180                return;
    -181            case ERROR:
    -182                logger.error(LogLevel.LOG_PREFIX + message);
    -183                if (throwable != null) {
    -184                    for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    -185                        logger.error(LogLevel.LOG_PREFIX + line);
    -186                    }
    -187                }
    -188        }
    -189    }
    -190
    -191    @Override
    -192    CommandOperationContext createCommandOperationContext(BaseCommand command, CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) {
    -193        return new SpongeCommandOperationContext(
    -194                this,
    -195                issuer,
    -196                command,
    -197                commandLabel,
    -198                args,
    -199                isAsync
    -200        );
    -201    }
    -202
    -203    @Override
    -204    public SpongeConditionContext createConditionContext(CommandIssuer issuer, String config) {
    -205        return new SpongeConditionContext((SpongeCommandIssuer) issuer, config);
    -206    }
    -207
    -208    @Override
    -209    public String getCommandPrefix(CommandIssuer issuer) {
    -210        return issuer.isPlayer() ? "/" : "";
    -211    }
    -212}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    +027import co.aikar.timings.Timing;
    +028import co.aikar.timings.Timings;
    +029import org.slf4j.Logger;
    +030import org.spongepowered.api.Sponge;
    +031import org.spongepowered.api.command.CommandSource;
    +032import org.spongepowered.api.plugin.PluginContainer;
    +033import org.spongepowered.api.text.format.TextColor;
    +034import org.spongepowered.api.text.format.TextColors;
    +035
    +036import java.lang.reflect.Method;
    +037import java.util.Collection;
    +038import java.util.Collections;
    +039import java.util.HashMap;
    +040import java.util.List;
    +041import java.util.Locale;
    +042import java.util.Map;
    +043
    +044@SuppressWarnings("WeakerAccess")
    +045public class SpongeCommandManager extends CommandManager<
    +046        CommandSource,
    +047        SpongeCommandIssuer,
    +048        TextColor,
    +049        SpongeMessageFormatter,
    +050        SpongeCommandExecutionContext,
    +051        SpongeConditionContext
    +052    > {
    +053
    +054    protected final PluginContainer plugin;
    +055    protected Map<String, SpongeRootCommand> registeredCommands = new HashMap<>();
    +056    protected SpongeCommandContexts contexts;
    +057    protected SpongeCommandCompletions completions;
    +058    private Timing commandTiming;
    +059    protected SpongeLocales locales;
    +060
    +061    public SpongeCommandManager(PluginContainer plugin) {
    +062        this.plugin = plugin;
    +063        String pluginName = "acf-" + plugin.getName();
    +064        getLocales().addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase(Locale.ENGLISH));
    +065        this.commandTiming = Timings.of(plugin, "Commands");
    +066
    +067        this.formatters.put(MessageType.ERROR, defaultFormatter = new SpongeMessageFormatter(TextColors.RED, TextColors.YELLOW, TextColors.RED));
    +068        this.formatters.put(MessageType.SYNTAX, new SpongeMessageFormatter(TextColors.YELLOW, TextColors.GREEN, TextColors.WHITE));
    +069        this.formatters.put(MessageType.INFO, new SpongeMessageFormatter(TextColors.BLUE, TextColors.DARK_GREEN, TextColors.GREEN));
    +070        this.formatters.put(MessageType.HELP, new SpongeMessageFormatter(TextColors.AQUA, TextColors.GREEN, TextColors.YELLOW));
    +071        getLocales(); // auto load locales
    +072
    +073        Sponge.getEventManager().registerListeners(plugin, new ACFSpongeListener(this));
    +074
    +075        //TODO more default dependencies for sponge
    +076        registerDependency(plugin.getClass(), plugin);
    +077    }
    +078
    +079    public PluginContainer getPlugin() {
    +080        return plugin;
    +081    }
    +082
    +083    @Override
    +084    public boolean isCommandIssuer(Class<?> type) {
    +085        return CommandSource.class.isAssignableFrom(type);
    +086    }
    +087
    +088    @Override
    +089    public synchronized CommandContexts<SpongeCommandExecutionContext> getCommandContexts() {
    +090        if (this.contexts == null) {
    +091            this.contexts = new SpongeCommandContexts(this);
    +092        }
    +093        return contexts;
    +094    }
    +095
    +096    @Override
    +097    public synchronized CommandCompletions<SpongeCommandCompletionContext> getCommandCompletions() {
    +098        if (this.completions == null) {
    +099            this.completions = new SpongeCommandCompletions(this);
    +100        }
    +101        return completions;
    +102    }
    +103
    +104    @Override
    +105    public SpongeLocales getLocales() {
    +106        if (this.locales == null) {
    +107            this.locales = new SpongeLocales(this);
    +108            this.locales.loadLanguages();
    +109        }
    +110        return locales;
    +111    }
    +112
    +113    @Override
    +114    public boolean hasRegisteredCommands() {
    +115        return !registeredCommands.isEmpty();
    +116    }
    +117
    +118    @Override
    +119    public void registerCommand(BaseCommand command) {
    +120        command.onRegister(this);
    +121
    +122        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    +123            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
    +124            SpongeRootCommand spongeCommand = (SpongeRootCommand) entry.getValue();
    +125            if (!spongeCommand.isRegistered) {
    +126                Sponge.getCommandManager().register(this.plugin, spongeCommand, commandName);
    +127            }
    +128            spongeCommand.isRegistered = true;
    +129            registeredCommands.put(commandName, spongeCommand);
    +130        }
    +131    }
    +132
    +133    public Timing createTiming(final String name) {
    +134        return Timings.of(this.plugin, name, this.commandTiming);
    +135    }
    +136
    +137    @Override
    +138    public RootCommand createRootCommand(String cmd) {
    +139        return new SpongeRootCommand(this, cmd);
    +140    }
    +141    
    +142    @Override
    +143    public Collection<RootCommand> getRegisteredRootCommands() {
    +144        return Collections.unmodifiableCollection(registeredCommands.values());
    +145    }
    +146
    +147    @Override
    +148    public SpongeCommandIssuer getCommandIssuer(Object issuer) {
    +149        if (!(issuer instanceof CommandSource)) {
    +150            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
    +151        }
    +152        return new SpongeCommandIssuer(this, (CommandSource) issuer);
    +153    }
    +154
    +155    @Override
    +156    public SpongeCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
    +157        return new SpongeCommandExecutionContext(command, parameter, (SpongeCommandIssuer) sender, args, i, passedArgs);
    +158    }
    +159
    +160    @Override
    +161    public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
    +162        return new SpongeCommandCompletionContext(command, (SpongeCommandIssuer) sender, input, config, args);
    +163    }
    +164
    +165    @Override
    +166    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
    +167        return new SpongeRegisteredCommand(command, cmdName, method, prefSubCommand);
    +168    }
    +169
    +170    @Override
    +171    public void log(final LogLevel level, final String message, final Throwable throwable) {
    +172        Logger logger = this.plugin.getLogger();
    +173        switch(level) {
    +174            case INFO:
    +175                logger.info(LogLevel.LOG_PREFIX + message);
    +176                if (throwable != null) {
    +177                    for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    +178                        logger.info(LogLevel.LOG_PREFIX + line);
    +179                    }
    +180                }
    +181                return;
    +182            case ERROR:
    +183                logger.error(LogLevel.LOG_PREFIX + message);
    +184                if (throwable != null) {
    +185                    for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    +186                        logger.error(LogLevel.LOG_PREFIX + line);
    +187                    }
    +188                }
    +189        }
    +190    }
    +191
    +192    @Override
    +193    CommandOperationContext createCommandOperationContext(BaseCommand command, CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) {
    +194        return new SpongeCommandOperationContext(
    +195                this,
    +196                issuer,
    +197                command,
    +198                commandLabel,
    +199                args,
    +200                isAsync
    +201        );
    +202    }
    +203
    +204    @Override
    +205    public SpongeConditionContext createConditionContext(CommandIssuer issuer, String config) {
    +206        return new SpongeConditionContext((SpongeCommandIssuer) issuer, config);
    +207    }
    +208
    +209    @Override
    +210    public String getCommandPrefix(CommandIssuer issuer) {
    +211        return issuer.isPlayer() ? "/" : "";
    +212    }
    +213}
     
     
     
    @@ -280,5 +282,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandOperationContext.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandOperationContext.html index f9b989f7..f3a7f68e 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandOperationContext.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeCommandOperationContext.html @@ -1,29 +1,30 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import org.spongepowered.api.command.CommandResult;
    -004
    -005public class SpongeCommandOperationContext extends CommandOperationContext {
    -006    private CommandResult result = CommandResult.success();
    -007    SpongeCommandOperationContext(CommandManager manager, CommandIssuer issuer, BaseCommand command, String commandLabel, String[] args, boolean isAsync) {
    -008        super(manager, issuer, command, commandLabel, args, isAsync);
    -009    }
    -010
    -011    public CommandResult getResult() {
    -012        return result;
    -013    }
    -014
    -015    public void setResult(CommandResult result) {
    -016        this.result = result;
    -017    }
    -018}
    +
    001package co.aikar.commands;
    +002
    +003import org.spongepowered.api.command.CommandResult;
    +004
    +005public class SpongeCommandOperationContext extends CommandOperationContext {
    +006    private CommandResult result = CommandResult.success();
    +007    SpongeCommandOperationContext(CommandManager manager, CommandIssuer issuer, BaseCommand command, String commandLabel, String[] args, boolean isAsync) {
    +008        super(manager, issuer, command, commandLabel, args, isAsync);
    +009    }
    +010
    +011    public CommandResult getResult() {
    +012        return result;
    +013    }
    +014
    +015    public void setResult(CommandResult result) {
    +016        this.result = result;
    +017    }
    +018}
     
     
     
    @@ -86,5 +87,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeConditionContext.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeConditionContext.html index 7ab54251..017b7bcd 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeConditionContext.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeConditionContext.html @@ -1,30 +1,31 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import org.spongepowered.api.command.CommandSource;
    -004import org.spongepowered.api.entity.living.player.Player;
    -005
    -006public class SpongeConditionContext extends ConditionContext <SpongeCommandIssuer> {
    -007    SpongeConditionContext(SpongeCommandIssuer issuer, String config) {
    -008        super(issuer, config);
    -009    }
    -010
    -011
    -012    public CommandSource getSource() {
    -013        return getIssuer().getIssuer();
    -014    }
    -015
    -016    public Player getPlayer() {
    -017        return getIssuer().getPlayer();
    -018    }
    -019}
    +
    001package co.aikar.commands;
    +002
    +003import org.spongepowered.api.command.CommandSource;
    +004import org.spongepowered.api.entity.living.player.Player;
    +005
    +006public class SpongeConditionContext extends ConditionContext <SpongeCommandIssuer> {
    +007    SpongeConditionContext(SpongeCommandIssuer issuer, String config) {
    +008        super(issuer, config);
    +009    }
    +010
    +011
    +012    public CommandSource getSource() {
    +013        return getIssuer().getIssuer();
    +014    }
    +015
    +016    public Player getPlayer() {
    +017        return getIssuer().getPlayer();
    +018    }
    +019}
     
     
     
    @@ -87,5 +88,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeLocales.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeLocales.html index f357b9c1..7114d1fa 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeLocales.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeLocales.html @@ -1,29 +1,32 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003public class SpongeLocales extends Locales{
    -004    private final SpongeCommandManager manager;
    -005
    -006    public SpongeLocales(SpongeCommandManager manager) {
    -007        super(manager);
    -008        this.manager = manager;
    -009        this.addBundleClassLoader(this.manager.getPlugin().getClass().getClassLoader());
    -010    }
    -011
    -012    @Override
    -013    public void loadLanguages() {
    -014        super.loadLanguages();
    -015        String pluginName = "acf-" + manager.plugin.getName();
    -016        addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
    -017    }
    -018}
    +
    001package co.aikar.commands;
    +002
    +003import java.util.Locale;
    +004
    +005public class SpongeLocales extends Locales{
    +006    private final SpongeCommandManager manager;
    +007
    +008    public SpongeLocales(SpongeCommandManager manager) {
    +009        super(manager);
    +010        this.manager = manager;
    +011        this.addBundleClassLoader(this.manager.getPlugin().getClass().getClassLoader());
    +012    }
    +013
    +014    @Override
    +015    public void loadLanguages() {
    +016        super.loadLanguages();
    +017        String pluginName = "acf-" + manager.plugin.getName();
    +018        addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase(Locale.ENGLISH));
    +019    }
    +020}
     
     
     
    @@ -86,5 +89,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeMessageFormatter.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeMessageFormatter.html index 38f5290e..52dd6e1d 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeMessageFormatter.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeMessageFormatter.html @@ -1,27 +1,28 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import org.spongepowered.api.text.Text;
    -004import org.spongepowered.api.text.format.TextColor;
    -005import org.spongepowered.api.text.serializer.TextSerializers;
    -006
    -007public class SpongeMessageFormatter extends MessageFormatter<TextColor> {
    -008
    -009    public SpongeMessageFormatter(TextColor... colors) {
    -010        super(colors);
    -011    }
    -012
    -013    public String format(TextColor color, String message) {
    -014        return TextSerializers.LEGACY_FORMATTING_CODE.serialize(Text.of(color, message));
    -015    }
    -016}
    +
    001package co.aikar.commands;
    +002
    +003import org.spongepowered.api.text.Text;
    +004import org.spongepowered.api.text.format.TextColor;
    +005import org.spongepowered.api.text.serializer.TextSerializers;
    +006
    +007public class SpongeMessageFormatter extends MessageFormatter<TextColor> {
    +008
    +009    public SpongeMessageFormatter(TextColor... colors) {
    +010        super(colors);
    +011    }
    +012
    +013    public String format(TextColor color, String message) {
    +014        return TextSerializers.LEGACY_FORMATTING_CODE.serialize(Text.of(color, message));
    +015    }
    +016}
     
     
     
    @@ -84,5 +85,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeRegisteredCommand.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeRegisteredCommand.html index 121074be..06eba9b7 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeRegisteredCommand.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeRegisteredCommand.html @@ -1,61 +1,62 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import co.aikar.timings.Timing;
    -027
    -028import java.lang.reflect.Method;
    -029
    -030public class SpongeRegisteredCommand extends RegisteredCommand<SpongeCommandExecutionContext> {
    -031
    -032    private final Timing timing;
    -033
    -034    SpongeRegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) {
    -035        super(scope, command, method, prefSubCommand);
    -036        this.timing = ((SpongeCommandManager) scope.manager).createTiming("Command: " + this.command);
    -037    }
    -038
    -039    @Override
    -040    public void preCommand() {
    -041        this.timing.startTiming();
    -042        super.preCommand();
    -043    }
    -044
    -045    @Override
    -046    public void postCommand() {
    -047        super.postCommand();
    -048        this.timing.stopTiming();
    -049    }
    -050}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import co.aikar.timings.Timing;
    +027
    +028import java.lang.reflect.Method;
    +029
    +030public class SpongeRegisteredCommand extends RegisteredCommand<SpongeCommandExecutionContext> {
    +031
    +032    private final Timing timing;
    +033
    +034    SpongeRegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) {
    +035        super(scope, command, method, prefSubCommand);
    +036        this.timing = ((SpongeCommandManager) scope.manager).createTiming("Command: " + this.command);
    +037    }
    +038
    +039    @Override
    +040    public void preCommand() {
    +041        this.timing.startTiming();
    +042        super.preCommand();
    +043    }
    +044
    +045    @Override
    +046    public void postCommand() {
    +047        super.postCommand();
    +048        this.timing.stopTiming();
    +049    }
    +050}
     
     
     
    @@ -118,5 +119,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/SpongeRootCommand.html b/docs/acf-sponge/src-html/co/aikar/commands/SpongeRootCommand.html index f7413612..543baeea 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/SpongeRootCommand.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/SpongeRootCommand.html @@ -1,138 +1,139 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import com.google.common.collect.HashMultimap;
    -027import com.google.common.collect.SetMultimap;
    -028import org.jetbrains.annotations.NotNull;
    -029import org.spongepowered.api.command.CommandCallable;
    -030import org.spongepowered.api.command.CommandException;
    -031import org.spongepowered.api.command.CommandResult;
    -032import org.spongepowered.api.command.CommandSource;
    -033import org.spongepowered.api.text.Text;
    -034import org.spongepowered.api.world.Location;
    -035import org.spongepowered.api.world.World;
    -036
    -037import javax.annotation.Nullable;
    -038import java.util.ArrayList;
    -039import java.util.List;
    -040import java.util.Optional;
    -041
    -042public class SpongeRootCommand implements CommandCallable, RootCommand {
    -043
    -044    private final SpongeCommandManager manager;
    -045    private final String name;
    -046    private BaseCommand defCommand;
    -047    private SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
    -048    private List<BaseCommand> children = new ArrayList<>();
    -049    boolean isRegistered = false;
    -050
    -051    SpongeRootCommand(SpongeCommandManager manager, String name) {
    -052        this.manager = manager;
    -053        this.name = name;
    -054    }
    -055
    -056    @Override
    -057    public String getCommandName() {
    -058        return name;
    -059    }
    -060
    -061    @Override
    -062    public CommandResult process(@NotNull CommandSource source, @NotNull String arguments) throws CommandException {
    -063        String[] args = arguments.isEmpty() ? new String[0] : arguments.split(" ");
    -064        return this.executeSponge(manager.getCommandIssuer(source), this.name, args);
    -065    }
    -066
    -067    @Override
    -068    public List<String> getSuggestions(@NotNull CommandSource source, @NotNull String arguments, @Nullable Location<World> location) throws CommandException {
    -069        String[] args = arguments.isEmpty() ? new String[]{""} : arguments.split(" ");
    -070        return getTabCompletions(manager.getCommandIssuer(source), this.name, args);
    -071    }
    -072
    -073    @Override
    -074    public boolean testPermission(@NotNull CommandSource source) {
    -075        return this.hasAnyPermission(manager.getCommandIssuer(source));
    -076    }
    -077
    -078    @Override
    -079    public Optional<Text> getShortDescription(@NotNull CommandSource source) {
    -080        String description = getDescription();
    -081        return description != null ? Optional.of(Text.of(description)) : Optional.empty();
    -082    }
    -083
    -084    @Override
    -085    public Optional<Text> getHelp(@NotNull CommandSource source) {
    -086        return Optional.empty();
    -087    }
    -088
    -089    @Override
    -090    public Text getUsage(@NotNull CommandSource source) {
    -091        String usage = getUsage();
    -092        return usage != null ? Text.of(usage) : Text.of();
    -093    }
    -094
    -095    private CommandResult executeSponge(CommandIssuer sender, String commandLabel, String[] args) {
    -096        BaseCommand cmd = execute(sender, commandLabel, args);
    -097        SpongeCommandOperationContext lastContext = (SpongeCommandOperationContext) cmd.getLastCommandOperationContext();
    -098        return lastContext != null ? lastContext.getResult() : CommandResult.success();
    -099    }
    -100
    -101    public void addChild(BaseCommand command) {
    -102        if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) {
    -103            this.defCommand = command;
    -104        }
    -105        addChildShared(this.children, this.subCommands, command);
    -106    }
    -107
    -108    @Override
    -109    public BaseCommand getDefCommand() {
    -110        return defCommand;
    -111    }
    -112
    -113    @Override
    -114    public CommandManager getManager() {
    -115        return manager;
    -116    }
    -117
    -118    @Override
    -119    public SetMultimap<String, RegisteredCommand> getSubCommands() {
    -120        return subCommands;
    -121    }
    -122
    -123    @Override
    -124    public List<BaseCommand> getChildren() {
    -125        return children;
    -126    }
    -127}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import com.google.common.collect.HashMultimap;
    +027import com.google.common.collect.SetMultimap;
    +028import org.jetbrains.annotations.NotNull;
    +029import org.spongepowered.api.command.CommandCallable;
    +030import org.spongepowered.api.command.CommandException;
    +031import org.spongepowered.api.command.CommandResult;
    +032import org.spongepowered.api.command.CommandSource;
    +033import org.spongepowered.api.text.Text;
    +034import org.spongepowered.api.world.Location;
    +035import org.spongepowered.api.world.World;
    +036
    +037import javax.annotation.Nullable;
    +038import java.util.ArrayList;
    +039import java.util.List;
    +040import java.util.Optional;
    +041
    +042public class SpongeRootCommand implements CommandCallable, RootCommand {
    +043
    +044    private final SpongeCommandManager manager;
    +045    private final String name;
    +046    private BaseCommand defCommand;
    +047    private SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
    +048    private List<BaseCommand> children = new ArrayList<>();
    +049    boolean isRegistered = false;
    +050
    +051    SpongeRootCommand(SpongeCommandManager manager, String name) {
    +052        this.manager = manager;
    +053        this.name = name;
    +054    }
    +055
    +056    @Override
    +057    public String getCommandName() {
    +058        return name;
    +059    }
    +060
    +061    @Override
    +062    public CommandResult process(@NotNull CommandSource source, @NotNull String arguments) throws CommandException {
    +063        String[] args = arguments.isEmpty() ? new String[0] : arguments.split(" ");
    +064        return this.executeSponge(manager.getCommandIssuer(source), this.name, args);
    +065    }
    +066
    +067    @Override
    +068    public List<String> getSuggestions(@NotNull CommandSource source, @NotNull String arguments, @Nullable Location<World> location) throws CommandException {
    +069        String[] args = arguments.isEmpty() ? new String[]{""} : arguments.split(" ");
    +070        return getTabCompletions(manager.getCommandIssuer(source), this.name, args);
    +071    }
    +072
    +073    @Override
    +074    public boolean testPermission(@NotNull CommandSource source) {
    +075        return this.hasAnyPermission(manager.getCommandIssuer(source));
    +076    }
    +077
    +078    @Override
    +079    public Optional<Text> getShortDescription(@NotNull CommandSource source) {
    +080        String description = getDescription();
    +081        return description != null ? Optional.of(Text.of(description)) : Optional.empty();
    +082    }
    +083
    +084    @Override
    +085    public Optional<Text> getHelp(@NotNull CommandSource source) {
    +086        return Optional.empty();
    +087    }
    +088
    +089    @Override
    +090    public Text getUsage(@NotNull CommandSource source) {
    +091        String usage = getUsage();
    +092        return usage != null ? Text.of(usage) : Text.of();
    +093    }
    +094
    +095    private CommandResult executeSponge(CommandIssuer sender, String commandLabel, String[] args) {
    +096        BaseCommand cmd = execute(sender, commandLabel, args);
    +097        SpongeCommandOperationContext lastContext = (SpongeCommandOperationContext) cmd.getLastCommandOperationContext();
    +098        return lastContext != null ? lastContext.getResult() : CommandResult.success();
    +099    }
    +100
    +101    public void addChild(BaseCommand command) {
    +102        if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) {
    +103            this.defCommand = command;
    +104        }
    +105        addChildShared(this.children, this.subCommands, command);
    +106    }
    +107
    +108    @Override
    +109    public BaseCommand getDefCommand() {
    +110        return defCommand;
    +111    }
    +112
    +113    @Override
    +114    public CommandManager getManager() {
    +115        return manager;
    +116    }
    +117
    +118    @Override
    +119    public SetMultimap<String, RegisteredCommand> getSubCommands() {
    +120        return subCommands;
    +121    }
    +122
    +123    @Override
    +124    public List<BaseCommand> getChildren() {
    +125        return children;
    +126    }
    +127}
     
     
     
    @@ -195,5 +196,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/contexts/CommandResultSupplier.html b/docs/acf-sponge/src-html/co/aikar/commands/contexts/CommandResultSupplier.html index a040a783..0b78f4fd 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/contexts/CommandResultSupplier.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/contexts/CommandResultSupplier.html @@ -1,30 +1,31 @@ - + Source code +
    -
    001package co.aikar.commands.contexts;
    -002
    -003import co.aikar.commands.CommandManager;
    -004import co.aikar.commands.SpongeCommandOperationContext;
    -005import org.spongepowered.api.command.CommandResult;
    -006
    -007import java.util.function.Consumer;
    -008
    -009public class CommandResultSupplier implements Consumer<CommandResult> {
    -010
    -011    public CommandResultSupplier() {
    -012    }
    -013
    -014    @Override
    -015    public void accept(CommandResult commandResult) {
    -016        SpongeCommandOperationContext context = (SpongeCommandOperationContext) CommandManager.getCurrentCommandOperationContext();
    -017        context.setResult(commandResult);
    -018    }
    -019}
    +
    001package co.aikar.commands.contexts;
    +002
    +003import co.aikar.commands.CommandManager;
    +004import co.aikar.commands.SpongeCommandOperationContext;
    +005import org.spongepowered.api.command.CommandResult;
    +006
    +007import java.util.function.Consumer;
    +008
    +009public class CommandResultSupplier implements Consumer<CommandResult> {
    +010
    +011    public CommandResultSupplier() {
    +012    }
    +013
    +014    @Override
    +015    public void accept(CommandResult commandResult) {
    +016        SpongeCommandOperationContext context = (SpongeCommandOperationContext) CommandManager.getCurrentCommandOperationContext();
    +017        context.setResult(commandResult);
    +018    }
    +019}
     
     
     
    @@ -87,5 +88,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/contexts/OnlinePlayer.html b/docs/acf-sponge/src-html/co/aikar/commands/contexts/OnlinePlayer.html index 0eba5312..3a7b9069 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/contexts/OnlinePlayer.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/contexts/OnlinePlayer.html @@ -1,47 +1,48 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands.contexts;
    -025
    -026import org.spongepowered.api.entity.living.player.Player;
    -027
    -028/**
    -029 * @deprecated Use {@link co.aikar.commands.sponge.contexts.OnlinePlayer instead}
    -030 */
    -031@Deprecated
    -032public class OnlinePlayer extends co.aikar.commands.sponge.contexts.OnlinePlayer {
    -033    public OnlinePlayer(Player player) {
    -034        super(player);
    -035    }
    -036}
    +
    001/*
    +002 * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands.contexts;
    +025
    +026import org.spongepowered.api.entity.living.player.Player;
    +027
    +028/**
    +029 * @deprecated Use {@link co.aikar.commands.sponge.contexts.OnlinePlayer instead}
    +030 */
    +031@Deprecated
    +032public class OnlinePlayer extends co.aikar.commands.sponge.contexts.OnlinePlayer {
    +033    public OnlinePlayer(Player player) {
    +034        super(player);
    +035    }
    +036}
     
     
     
    @@ -104,5 +105,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/src-html/co/aikar/commands/sponge/contexts/OnlinePlayer.html b/docs/acf-sponge/src-html/co/aikar/commands/sponge/contexts/OnlinePlayer.html index b4017acb..87923264 100644 --- a/docs/acf-sponge/src-html/co/aikar/commands/sponge/contexts/OnlinePlayer.html +++ b/docs/acf-sponge/src-html/co/aikar/commands/sponge/contexts/OnlinePlayer.html @@ -1,69 +1,70 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands.sponge.contexts;
    -025
    -026import org.spongepowered.api.entity.living.player.Player;
    -027
    -028import java.util.Objects;
    -029
    -030public class OnlinePlayer {
    -031    public final Player player;
    -032
    -033    public OnlinePlayer(Player player) {
    -034        this.player = player;
    -035    }
    -036
    -037    public Player getPlayer() {
    -038        return this.player;
    -039    }
    -040
    -041    @Override
    -042    public boolean equals(Object o) {
    -043        if (this == o) return true;
    -044        if (o == null || getClass() != o.getClass()) return false;
    -045        OnlinePlayer that = (OnlinePlayer) o;
    -046        return Objects.equals(player, that.player);
    -047    }
    -048
    -049    @Override
    -050    public int hashCode() {
    -051        return Objects.hash(player);
    -052    }
    -053
    -054    @Override
    -055    public String toString() {
    -056        return "OnlinePlayer{player=" + player + '}';
    -057    }
    -058}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands.sponge.contexts;
    +025
    +026import org.spongepowered.api.entity.living.player.Player;
    +027
    +028import java.util.Objects;
    +029
    +030public class OnlinePlayer {
    +031    public final Player player;
    +032
    +033    public OnlinePlayer(Player player) {
    +034        this.player = player;
    +035    }
    +036
    +037    public Player getPlayer() {
    +038        return this.player;
    +039    }
    +040
    +041    @Override
    +042    public boolean equals(Object o) {
    +043        if (this == o) return true;
    +044        if (o == null || getClass() != o.getClass()) return false;
    +045        OnlinePlayer that = (OnlinePlayer) o;
    +046        return Objects.equals(player, that.player);
    +047    }
    +048
    +049    @Override
    +050    public int hashCode() {
    +051        return Objects.hash(player);
    +052    }
    +053
    +054    @Override
    +055    public String toString() {
    +056        return "OnlinePlayer{player=" + player + '}';
    +057    }
    +058}
     
     
     
    @@ -126,5 +127,6 @@
     
     
    +
    diff --git a/docs/acf-sponge/stylesheet.css b/docs/acf-sponge/stylesheet.css index 98055b22..fa246765 100644 --- a/docs/acf-sponge/stylesheet.css +++ b/docs/acf-sponge/stylesheet.css @@ -1,35 +1,51 @@ -/* Javadoc style sheet */ -/* -Overall document style -*/ +/* + * Javadoc style sheet + */ @import url('resources/fonts/dejavu.css'); +/* + * Styles for individual HTML elements. + * + * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular + * HTML element throughout the page. + */ + body { background-color:#ffffff; color:#353833; font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; font-size:14px; margin:0; + padding:0; + height:100%; + width:100%; +} +iframe { + margin:0; + padding:0; + height:100%; + width:100%; + overflow-y:scroll; + border:none; } a:link, a:visited { text-decoration:none; color:#4A6782; } -a:hover, a:focus { +a[href]:hover, a[href]:focus { text-decoration:none; color:#bb7a2a; } -a:active { - text-decoration:none; - color:#4A6782; -} a[name] { color:#353833; } -a[name]:hover { - text-decoration:none; - color:#353833; +a[name]:before, a[name]:target, a[id]:before, a[id]:target { + content:""; + display:inline-block; + position:relative; + padding-top:129px; + margin-top:-129px; } pre { font-family:'DejaVu Sans Mono', monospace; @@ -78,9 +94,16 @@ table tr td dt code { sup { font-size:8px; } + /* -Document title and Copyright styles -*/ + * Styles for HTML generated by javadoc. + * + * These are style classes that are used by the standard doclet to generate HTML documentation. + */ + +/* + * Styles for document title and copyright. + */ .clear { clear:both; height:0px; @@ -111,8 +134,8 @@ Document title and Copyright styles font-weight:bold; } /* -Navigation bar styles -*/ + * Styles for navigation bar. + */ .bar { background-color:#4D7A97; color:#FFFFFF; @@ -121,6 +144,15 @@ Navigation bar styles font-size:11px; margin:0; } +.navPadding { + padding-top: 107px; +} +.fixedNav { + position:fixed; + width:100%; + z-index:999; + background-color:#ffffff; +} .topNav { background-color:#4D7A97; color:#FFFFFF; @@ -170,7 +202,22 @@ ul.navList li{ padding: 5px 6px; text-transform:uppercase; } -ul.subNavList li{ +ul.navListSearch { + float:right; + margin:0 0 0 0; + padding:0; +} +ul.navListSearch li { + list-style:none; + float:right; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch li label { + position:relative; + right:-16px; +} +ul.subNavList li { list-style:none; float:left; } @@ -196,21 +243,29 @@ ul.subNavList li{ overflow:hidden; } /* -Page header and footer styles -*/ + * Styles for page header and footer. + */ .header, .footer { clear:both; margin:0 20px; padding:5px 0 0 0; } -.indexHeader { - margin:10px; +.indexNav { position:relative; + font-size:12px; + background-color:#dee3e9; } -.indexHeader span{ - margin-right:15px; +.indexNav ul { + margin-top:0; + padding:5px; } -.indexHeader h1 { +.indexNav ul li { + display:inline; + list-style-type:none; + padding-right:10px; + text-transform:uppercase; +} +.indexNav h1 { font-size:13px; } .title { @@ -232,8 +287,8 @@ Page header and footer styles font-size:13px; } /* -Heading styles -*/ + * Styles for headings. + */ div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { background-color:#dee3e9; border:1px solid #d0d9e0; @@ -254,9 +309,10 @@ ul.blockList li.blockList h2 { padding:0px 0 20px 0; } /* -Page layout container styles -*/ -.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + * Styles for page layout containers. + */ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer, +.allClassesContainer, .allPackagesContainer { clear:both; padding:10px 20px; position:relative; @@ -287,7 +343,7 @@ Page layout container styles .contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { margin:5px 0 10px 0px; font-size:14px; - font-family:'DejaVu Sans Mono',monospace; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } .serializedFormContainer dl.nameValue dt { margin-left:1px; @@ -301,8 +357,11 @@ Page layout container styles display:inline; } /* -List styles -*/ + * Styles for lists. + */ +li.circle { + list-style:circle; +} ul.horizontal li { display:inline; font-size:0.9em; @@ -355,19 +414,22 @@ table tr td dl, table tr td dl dt, table tr td dl dd { margin-bottom:1px; } /* -Table styles -*/ -.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + * Styles for tables. + */ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary, +.requiresSummary, .packagesSummary, .providesSummary, .usesSummary { width:100%; + border-spacing:0; border-left:1px solid #EEE; border-right:1px solid #EEE; border-bottom:1px solid #EEE; } -.overviewSummary, .memberSummary { +.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary { padding:0px; } .overviewSummary caption, .memberSummary caption, .typeSummary caption, -.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption, +.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption { position:relative; text-align:left; background-repeat:no-repeat; @@ -382,17 +444,31 @@ Table styles white-space:pre; } .overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, -.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.constantsSummary caption a:link, .deprecatedSummary caption a:link, +.requiresSummary caption a:link, .packagesSummary caption a:link, .providesSummary caption a:link, +.usesSummary caption a:link, .overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, -.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.requiresSummary caption a:hover, .packagesSummary caption a:hover, .providesSummary caption a:hover, +.usesSummary caption a:hover, .overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, -.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.constantsSummary caption a:active, .deprecatedSummary caption a:active, +.requiresSummary caption a:active, .packagesSummary caption a:active, .providesSummary caption a:active, +.usesSummary caption a:active, .overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, -.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { +.constantsSummary caption a:visited, .deprecatedSummary caption a:visited, +.requiresSummary caption a:visited, .packagesSummary caption a:visited, .providesSummary caption a:visited, +.usesSummary caption a:visited { color:#FFFFFF; } +.useSummary caption a:link, .useSummary caption a:hover, .useSummary caption a:active, +.useSummary caption a:visited { + color:#1f389c; +} .overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, -.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span, +.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span, +.usesSummary caption span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -404,7 +480,8 @@ Table styles border: none; height:16px; } -.memberSummary caption span.activeTableTab span { +.memberSummary caption span.activeTableTab span, .packagesSummary caption span.activeTableTab span, +.overviewSummary caption span.activeTableTab span, .typeSummary caption span.activeTableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -415,7 +492,8 @@ Table styles background-color:#F8981D; height:16px; } -.memberSummary caption span.tableTab span { +.memberSummary caption span.tableTab span, .packagesSummary caption span.tableTab span, +.overviewSummary caption span.tableTab span, .typeSummary caption span.tableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -426,7 +504,10 @@ Table styles background-color:#4D7A97; height:16px; } -.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab, +.packagesSummary caption span.tableTab, .packagesSummary caption span.activeTableTab, +.overviewSummary caption span.tableTab, .overviewSummary caption span.activeTableTab, +.typeSummary caption span.tableTab, .typeSummary caption span.activeTableTab { padding-top:0px; padding-left:0px; padding-right:0px; @@ -435,14 +516,16 @@ Table styles display:inline; } .overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, -.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd, +.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd { display:none; width:5px; position:relative; float:left; background-color:#F8981D; } -.memberSummary .activeTableTab .tabEnd { +.memberSummary .activeTableTab .tabEnd, .packagesSummary .activeTableTab .tabEnd, +.overviewSummary .activeTableTab .tabEnd, .typeSummary .activeTableTab .tabEnd { display:none; width:5px; margin-right:3px; @@ -450,66 +533,88 @@ Table styles float:left; background-color:#F8981D; } -.memberSummary .tableTab .tabEnd { +.memberSummary .tableTab .tabEnd, .packagesSummary .tableTab .tabEnd, +.overviewSummary .tableTab .tabEnd, .typeSummary .tableTab .tabEnd { display:none; width:5px; margin-right:3px; position:relative; background-color:#4D7A97; float:left; - +} +.rowColor th, .altColor th { + font-weight:normal; } .overviewSummary td, .memberSummary td, .typeSummary td, -.useSummary td, .constantsSummary td, .deprecatedSummary td { +.useSummary td, .constantsSummary td, .deprecatedSummary td, +.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td { text-align:left; padding:0px 0px 12px 10px; } -th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, -td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .useSummary th, +.constantsSummary th, .packagesSummary th, td.colFirst, td.colSecond, td.colLast, .useSummary td, +.constantsSummary td { vertical-align:top; padding-right:0px; padding-top:8px; padding-bottom:3px; } -th.colFirst, th.colLast, th.colOne, .constantsSummary th { +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .constantsSummary th, +.packagesSummary th { background:#dee3e9; text-align:left; padding:8px 3px 3px 7px; } td.colFirst, th.colFirst { - white-space:nowrap; font-size:13px; } -td.colLast, th.colLast { +td.colSecond, th.colSecond, td.colLast, th.colConstructorName, th.colDeprecatedItemName, th.colLast { font-size:13px; } -td.colOne, th.colOne { +.constantsSummary th, .packagesSummary th { + font-size:13px; +} +.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst, +.providesSummary td.colLast { + white-space:normal; font-size:13px; } .overviewSummary td.colFirst, .overviewSummary th.colFirst, -.useSummary td.colFirst, .useSummary th.colFirst, -.overviewSummary td.colOne, .overviewSummary th.colOne, +.requiresSummary td.colFirst, .requiresSummary th.colFirst, +.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th, +.usesSummary td.colFirst, .usesSummary th.colFirst, +.providesSummary td.colFirst, .providesSummary th.colFirst, .memberSummary td.colFirst, .memberSummary th.colFirst, -.memberSummary td.colOne, .memberSummary th.colOne, -.typeSummary td.colFirst{ - width:25%; +.memberSummary td.colSecond, .memberSummary th.colSecond, .memberSummary th.colConstructorName, +.typeSummary td.colFirst, .typeSummary th.colFirst { vertical-align:top; } -td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { +.packagesSummary th.colLast, .packagesSummary td.colLast { + white-space:normal; +} +td.colFirst a:link, td.colFirst a:visited, +td.colSecond a:link, td.colSecond a:visited, +th.colFirst a:link, th.colFirst a:visited, +th.colSecond a:link, th.colSecond a:visited, +th.colConstructorName a:link, th.colConstructorName a:visited, +th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited, +.constantValuesContainer td a:link, .constantValuesContainer td a:visited, +.allClassesContainer td a:link, .allClassesContainer td a:visited, +.allPackagesContainer td a:link, .allPackagesContainer td a:visited { font-weight:bold; } .tableSubHeadingColor { background-color:#EEEEFF; } -.altColor { +.altColor, .altColor th { background-color:#FFFFFF; } -.rowColor { +.rowColor, .rowColor th { background-color:#EEEEEF; } /* -Content styles -*/ + * Styles for contents. + */ .description pre { margin-top:0; } @@ -520,27 +625,22 @@ Content styles .docSummary { padding:0; } - ul.blockList ul.blockList ul.blockList li.blockList h3 { font-style:normal; } - div.block { font-size:14px; font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } - td.colLast div { padding-top:0px; } - - td.colLast a { padding-bottom:3px; } /* -Formatting effect styles -*/ + * Styles for formatting effect. + */ .sourceLineNo { color:green; padding:0 30px 0 0; @@ -555,20 +655,252 @@ h1.hidden { margin:3px 10px 2px 0px; color:#474747; } -.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { +.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink, +.moduleLabelInPackage, .moduleLabelInType, .overrideSpecifyLabel, .packageLabelInType, +.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, +.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { font-weight:bold; } .deprecationComment, .emphasizedPhrase, .interfaceName { font-style:italic; } - -div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +.deprecationBlock { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +div.block div.deprecationComment, div.block div.block span.emphasizedPhrase, div.block div.block span.interfaceName { font-style:normal; } - -div.contentContainer ul.blockList li.blockList h2{ +div.contentContainer ul.blockList li.blockList h2 { padding-bottom:0px; } +/* + * Styles for IFRAME. + */ +.mainContainer { + margin:0 auto; + padding:0; + height:100%; + width:100%; + position:fixed; + top:0; + left:0; +} +.leftContainer { + height:100%; + position:fixed; + width:320px; +} +.leftTop { + position:relative; + float:left; + width:315px; + top:0; + left:0; + height:30%; + border-right:6px solid #ccc; + border-bottom:6px solid #ccc; +} +.leftBottom { + position:relative; + float:left; + width:315px; + bottom:0; + left:0; + height:70%; + border-right:6px solid #ccc; + border-top:1px solid #000; +} +.rightContainer { + position:absolute; + left:320px; + top:0; + bottom:0; + height:100%; + right:0; + border-left:1px solid #000; +} +.rightIframe { + margin:0; + padding:0; + height:100%; + right:30px; + width:100%; + overflow:visible; + margin-bottom:30px; +} +/* + * Styles specific to HTML5 elements. + */ +main, nav, header, footer, section { + display:block; +} +/* + * Styles for javadoc search. + */ +.ui-autocomplete-category { + font-weight:bold; + font-size:15px; + padding:7px 0 7px 3px; + background-color:#4D7A97; + color:#FFFFFF; +} +.resultItem { + font-size:13px; +} +.ui-autocomplete { + max-height:85%; + max-width:65%; + overflow-y:scroll; + overflow-x:scroll; + white-space:nowrap; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); +} +ul.ui-autocomplete { + position:fixed; + z-index:999999; +} +ul.ui-autocomplete li { + float:left; + clear:both; + width:100%; +} +.resultHighlight { + font-weight:bold; +} +#search { + background-image:url('resources/glass.png'); + background-size:13px; + background-repeat:no-repeat; + background-position:2px 3px; + padding-left:20px; + position:relative; + right:-18px; +} +#reset { + background-color: rgb(255,255,255); + background-image:url('resources/x.png'); + background-position:center; + background-repeat:no-repeat; + background-size:12px; + border:0 none; + width:16px; + height:17px; + position:relative; + left:-4px; + top:-4px; + font-size:0px; +} +.watermark { + color:#545454; +} +.searchTagDescResult { + font-style:italic; + font-size:11px; +} +.searchTagHolderResult { + font-style:italic; + font-size:12px; +} +.searchTagResult:before, .searchTagResult:target { + color:red; +} +.moduleGraph span { + display:none; + position:absolute; +} +.moduleGraph:hover span { + display:block; + margin: -100px 0 0 100px; + z-index: 1; +} +.methodSignature { + white-space:normal; +} + +/* + * Styles for user-provided tables. + * + * borderless: + * No borders, vertical margins, styled caption. + * This style is provided for use with existing doc comments. + * In general, borderless tables should not be used for layout purposes. + * + * plain: + * Plain borders around table and cells, vertical margins, styled caption. + * Best for small tables or for complex tables for tables with cells that span + * rows and columns, when the "striped" style does not work well. + * + * striped: + * Borders around the table and vertical borders between cells, striped rows, + * vertical margins, styled caption. + * Best for tables that have a header row, and a body containing a series of simple rows. + */ + +table.borderless, +table.plain, +table.striped { + margin-top: 10px; + margin-bottom: 10px; +} +table.borderless > caption, +table.plain > caption, +table.striped > caption { + font-weight: bold; + font-size: smaller; +} +table.borderless th, table.borderless td, +table.plain th, table.plain td, +table.striped th, table.striped td { + padding: 2px 5px; +} +table.borderless, +table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, +table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { + border: none; +} +table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { + background-color: transparent; +} +table.plain { + border-collapse: collapse; + border: 1px solid black; +} +table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { + background-color: transparent; +} +table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, +table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { + border: 1px solid black; +} +table.striped { + border-collapse: collapse; + border: 1px solid black; +} +table.striped > thead { + background-color: #E3E3E3; +} +table.striped > thead > tr > th, table.striped > thead > tr > td { + border: 1px solid black; +} +table.striped > tbody > tr:nth-child(even) { + background-color: #EEE +} +table.striped > tbody > tr:nth-child(odd) { + background-color: #FFF +} +table.striped > tbody > tr > th, table.striped > tbody > tr > td { + border-left: 1px solid black; + border-right: 1px solid black; +} +table.striped > tbody > tr > th { + font-weight: normal; +} diff --git a/docs/acf-sponge/type-search-index.js b/docs/acf-sponge/type-search-index.js new file mode 100644 index 00000000..dfa71ef9 --- /dev/null +++ b/docs/acf-sponge/type-search-index.js @@ -0,0 +1 @@ +typeSearchIndex = [{"p":"co.aikar.commands","l":"ACFSpongeListener"},{"p":"co.aikar.commands","l":"ACFSpongeUtil"},{"l":"All Classes","url":"allclasses-index.html"},{"p":"co.aikar.commands.contexts","l":"CommandResultSupplier"},{"p":"co.aikar.commands","l":"MinecraftMessageKeys"},{"p":"co.aikar.commands.contexts","l":"OnlinePlayer"},{"p":"co.aikar.commands.sponge.contexts","l":"OnlinePlayer"},{"p":"co.aikar.commands","l":"SpongeCommandCompletionContext"},{"p":"co.aikar.commands","l":"SpongeCommandCompletions"},{"p":"co.aikar.commands","l":"SpongeCommandContexts"},{"p":"co.aikar.commands","l":"SpongeCommandExecutionContext"},{"p":"co.aikar.commands","l":"SpongeCommandIssuer"},{"p":"co.aikar.commands","l":"SpongeCommandManager"},{"p":"co.aikar.commands","l":"SpongeCommandOperationContext"},{"p":"co.aikar.commands","l":"SpongeConditionContext"},{"p":"co.aikar.commands","l":"SpongeLocales"},{"p":"co.aikar.commands","l":"SpongeMessageFormatter"},{"p":"co.aikar.commands","l":"SpongeRegisteredCommand"},{"p":"co.aikar.commands","l":"SpongeRootCommand"}] \ No newline at end of file diff --git a/docs/acf-sponge/type-search-index.zip b/docs/acf-sponge/type-search-index.zip new file mode 100644 index 00000000..9e104f93 Binary files /dev/null and b/docs/acf-sponge/type-search-index.zip differ diff --git a/docs/acf-velocity/allclasses-index.html b/docs/acf-velocity/allclasses-index.html new file mode 100644 index 00000000..a45b7aa8 --- /dev/null +++ b/docs/acf-velocity/allclasses-index.html @@ -0,0 +1,227 @@ + + + + + +All Classes (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    All Classes

    +
    + +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + + diff --git a/docs/acf-velocity/allclasses.html b/docs/acf-velocity/allclasses.html new file mode 100644 index 00000000..49987370 --- /dev/null +++ b/docs/acf-velocity/allclasses.html @@ -0,0 +1,42 @@ + + + + + +All Classes (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + +

    All Classes

    +
    + +
    + + diff --git a/docs/acf-velocity/allpackages-index.html b/docs/acf-velocity/allpackages-index.html new file mode 100644 index 00000000..da79c11f --- /dev/null +++ b/docs/acf-velocity/allpackages-index.html @@ -0,0 +1,173 @@ + + + + + +All Packages (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    All Packages

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + + diff --git a/docs/acf-velocity/co/aikar/commands/ACFVelocityListener.html b/docs/acf-velocity/co/aikar/commands/ACFVelocityListener.html index 82d18085..03355a59 100644 --- a/docs/acf-velocity/co/aikar/commands/ACFVelocityListener.html +++ b/docs/acf-velocity/co/aikar/commands/ACFVelocityListener.html @@ -1,12 +1,21 @@ - + - ACFVelocityListener (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class ACFVelocityListener

    @@ -117,58 +140,68 @@ extends
  • +
    +
    +
    +
  • @@ -176,74 +209,81 @@ extends
  • +
    +
    +
      -
    • +
    • Method Detail

      - +
      • onPlayerJoin

        -
        public void onPlayerJoin(com.velocitypowered.api.event.connection.PostLoginEvent loginEvent)
        +
        public void onPlayerJoin​(com.velocitypowered.api.event.connection.PostLoginEvent loginEvent)
      - +
      • onDisconnect

        -
        public void onDisconnect(com.velocitypowered.api.event.connection.DisconnectEvent disconnectEvent)
        +
        public void onDisconnect​(com.velocitypowered.api.event.connection.DisconnectEvent disconnectEvent)
      - +
      • onSettingsChange

        -
        public void onSettingsChange(com.velocitypowered.api.event.player.PlayerSettingsChangedEvent settingsEvent)
        +
        public void onSettingsChange​(com.velocitypowered.api.event.player.PlayerSettingsChangedEvent settingsEvent)
    +
  • + + diff --git a/docs/acf-velocity/co/aikar/commands/ACFVelocityUtil.html b/docs/acf-velocity/co/aikar/commands/ACFVelocityUtil.html index bd3012f0..f8ce9096 100644 --- a/docs/acf-velocity/co/aikar/commands/ACFVelocityUtil.html +++ b/docs/acf-velocity/co/aikar/commands/ACFVelocityUtil.html @@ -1,12 +1,21 @@ - + - ACFVelocityUtil (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class ACFVelocityUtil

    @@ -117,64 +140,75 @@ extends
  • +
    +
    +
    +
  • @@ -182,12 +216,13 @@ extends
  • +
      -
    • +
    • Constructor Detail

      - +
        @@ -198,71 +233,77 @@ extends
          -
        • +
        • Method Detail

          - +
          • color

            -
            public static net.kyori.text.TextComponent color(String message)
            +
            public static net.kyori.text.TextComponent color​(String message)
          - +
          • findPlayerSmart

            -
            public static com.velocitypowered.api.proxy.Player findPlayerSmart(com.velocitypowered.api.proxy.ProxyServer server,
            +
            public static com.velocitypowered.api.proxy.Player findPlayerSmart​(com.velocitypowered.api.proxy.ProxyServer server,
                                                                                co.aikar.commands.CommandIssuer issuer,
            -                                                                   String search)
            + String search)
          - + - + - +
        +
  • +
    + diff --git a/docs/acf-velocity/co/aikar/commands/MinecraftMessageKeys.html b/docs/acf-velocity/co/aikar/commands/MinecraftMessageKeys.html index 79f23447..ceca9022 100644 --- a/docs/acf-velocity/co/aikar/commands/MinecraftMessageKeys.html +++ b/docs/acf-velocity/co/aikar/commands/MinecraftMessageKeys.html @@ -1,12 +1,21 @@ - + - MinecraftMessageKeys (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Enum MinecraftMessageKeys

    @@ -208,73 +245,76 @@ the order they are declared. +
    + diff --git a/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletionContext.html b/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletionContext.html index 7d1424fa..0b7f735d 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletionContext.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletionContext.html @@ -1,12 +1,21 @@ - + - VelocityCommandCompletionContext (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class VelocityCommandCompletionContext

    @@ -122,13 +145,14 @@ extends co.aikar.commands.CommandCompletionContext<
  • +
  • @@ -180,46 +210,51 @@ extends co.aikar.commands.CommandCompletionContext<
  • +
      -
    • +
    • Method Detail

      - +
      • getSender

        -
        public com.velocitypowered.api.command.CommandSource getSender()
        +
        public com.velocitypowered.api.command.CommandSource getSender()
      - +
      • getPlayer

        -
        public com.velocitypowered.api.proxy.Player getPlayer()
        +
        public com.velocitypowered.api.proxy.Player getPlayer()
    +
  • +
    + diff --git a/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletions.html b/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletions.html index 7418b411..fe6d0aa8 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletions.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityCommandCompletions.html @@ -1,12 +1,21 @@ - + - VelocityCommandCompletions (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class VelocityCommandCompletions

    @@ -116,13 +139,14 @@ extends co.aikar.commands.CommandCompletions<
  • +
      -
    • +
    • Nested Class Summary

        -
      • +
      • Nested classes/interfaces inherited from class co.aikar.commands.CommandCompletions

        @@ -130,46 +154,53 @@ extends co.aikar.commands.CommandCompletions<
          -
        • +
        • Constructor Summary

          - +
          - + + - + +
          Constructors 
          Constructor and DescriptionConstructorDescription
          VelocityCommandCompletions(com.velocitypowered.api.proxy.ProxyServer server, - co.aikar.commands.CommandManager manager) VelocityCommandCompletions​(com.velocitypowered.api.proxy.ProxyServer server, + co.aikar.commands.CommandManager manager) 
        +
    +
    +
  • @@ -177,38 +208,43 @@ extends co.aikar.commands.CommandCompletions<
  • +
    +
  • +
    + diff --git a/docs/acf-velocity/co/aikar/commands/VelocityCommandContexts.html b/docs/acf-velocity/co/aikar/commands/VelocityCommandContexts.html index 9f41253a..164d8655 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityCommandContexts.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityCommandContexts.html @@ -1,12 +1,21 @@ - + - VelocityCommandContexts (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class VelocityCommandContexts

    @@ -116,13 +139,14 @@ extends co.aikar.commands.CommandContexts<
  • +
  • +
    + diff --git a/docs/acf-velocity/co/aikar/commands/VelocityCommandExecutionContext.html b/docs/acf-velocity/co/aikar/commands/VelocityCommandExecutionContext.html index a79d0017..acc6b872 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityCommandExecutionContext.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityCommandExecutionContext.html @@ -1,12 +1,21 @@ - + - VelocityCommandExecutionContext (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class VelocityCommandExecutionContext

    @@ -122,13 +145,14 @@ extends co.aikar.commands.CommandExecutionContext<
  • +
      -
    • +
    • Field Summary

        -
      • +
      • Fields inherited from class co.aikar.commands.CommandExecutionContext

        @@ -136,43 +160,49 @@ extends co.aikar.commands.CommandExecutionContext<
          -
        • +
        • Method Summary

          - +
          - + + - + + - + +
          All Methods Instance Methods Concrete Methods 
          Modifier and TypeMethod and DescriptionMethodDescription
          com.velocitypowered.api.proxy.PlayergetPlayer() getPlayer() 
          com.velocitypowered.api.command.CommandSourcegetSender() getSender() 
            -
          • +
          • Methods inherited from class co.aikar.commands.CommandExecutionContext

            canOverridePlayerContext, getAnnotation, getAnnotationValue, getAnnotationValue, getArgs, getBooleanFlagValue, getBooleanFlagValue, getCmd, getDoubleFlagValue, getFirstArg, getFlags, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFlagValue, getFloatFlagValue, getIndex, getIntFlagValue, getIssuer, getLastArg, getLongFlagValue, getNumParams, getParam, getParameterPermissions, getPassedArgs, getResolvedArg, getResolvedArg, getResolvedArg, hasAnnotation, hasFlag, isLastArg, isOptional, joinArgs, joinArgs, popFirstArg, popLastArg
        +
  • @@ -180,46 +210,51 @@ extends co.aikar.commands.CommandExecutionContext<
  • +
      -
    • +
    • Method Detail

      - +
      • getSender

        -
        public com.velocitypowered.api.command.CommandSource getSender()
        +
        public com.velocitypowered.api.command.CommandSource getSender()
      - +
      • getPlayer

        -
        public com.velocitypowered.api.proxy.Player getPlayer()
        +
        public com.velocitypowered.api.proxy.Player getPlayer()
    +
  • +
    + diff --git a/docs/acf-velocity/co/aikar/commands/VelocityCommandIssuer.html b/docs/acf-velocity/co/aikar/commands/VelocityCommandIssuer.html index 3f4fbe00..49b9d63e 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityCommandIssuer.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityCommandIssuer.html @@ -1,12 +1,21 @@ - + - VelocityCommandIssuer (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class VelocityCommandIssuer

    @@ -193,142 +228,147 @@ implements co.aikar.commands.CommandIssuer
    • +
        -
      • +
      • Method Detail

        - +
        • getIssuer

          -
          public com.velocitypowered.api.command.CommandSource getIssuer()
          +
          public com.velocitypowered.api.command.CommandSource getIssuer()
          Specified by:
          getIssuer in interface co.aikar.commands.CommandIssuer
        - +
        • getPlayer

          -
          public com.velocitypowered.api.proxy.Player getPlayer()
          +
          public com.velocitypowered.api.proxy.Player getPlayer()
        - +
        • getManager

          -
          public co.aikar.commands.CommandManager getManager()
          +
          public co.aikar.commands.CommandManager getManager()
          Specified by:
          getManager in interface co.aikar.commands.CommandIssuer
        - +
        • isPlayer

          -
          public boolean isPlayer()
          +
          public boolean isPlayer()
          Specified by:
          isPlayer in interface co.aikar.commands.CommandIssuer
        - +
        • getUniqueId

          -
          @NotNull
          -public @NotNull UUID getUniqueId()
          +
          @NotNull
          +public @NotNull UUID getUniqueId()
          Specified by:
          getUniqueId in interface co.aikar.commands.CommandIssuer
        - + - + - + - +
      +
    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/VelocityCommandManager.html b/docs/acf-velocity/co/aikar/commands/VelocityCommandManager.html index 4c961939..ff24a623 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityCommandManager.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityCommandManager.html @@ -1,12 +1,21 @@ - + - VelocityCommandManager (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class VelocityCommandManager

    @@ -122,44 +145,52 @@ extends co.aikar.commands.CommandManager<com.velocitypowered.api.command.Comm @@ -320,12 +380,13 @@ extends co.aikar.commands.CommandManager<com.velocitypowered.api.command.Comm +
    + diff --git a/docs/acf-velocity/co/aikar/commands/VelocityConditionContext.html b/docs/acf-velocity/co/aikar/commands/VelocityConditionContext.html index ce4bb066..400e2c65 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityConditionContext.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityConditionContext.html @@ -1,12 +1,21 @@ - + - VelocityConditionContext (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class VelocityConditionContext

    @@ -122,42 +145,47 @@ extends co.aikar.commands.ConditionContext<
  • +
    +
  • @@ -165,46 +193,51 @@ extends co.aikar.commands.ConditionContext<
  • +
      -
    • +
    • Method Detail

      - +
      • getSender

        -
        public com.velocitypowered.api.command.CommandSource getSender()
        +
        public com.velocitypowered.api.command.CommandSource getSender()
      - +
      • getPlayer

        -
        public com.velocitypowered.api.proxy.Player getPlayer()
        +
        public com.velocitypowered.api.proxy.Player getPlayer()
    +
  • +
    + diff --git a/docs/acf-velocity/co/aikar/commands/VelocityLocales.html b/docs/acf-velocity/co/aikar/commands/VelocityLocales.html index af054fc3..a438356a 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityLocales.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityLocales.html @@ -1,12 +1,21 @@ - + - VelocityLocales (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class VelocityLocales

    @@ -193,35 +226,38 @@ extends co.aikar.commands.Locales +
    + diff --git a/docs/acf-velocity/co/aikar/commands/VelocityMessageFormatter.html b/docs/acf-velocity/co/aikar/commands/VelocityMessageFormatter.html index 0d049921..dcecfd02 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityMessageFormatter.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityMessageFormatter.html @@ -1,12 +1,21 @@ - + - VelocityMessageFormatter (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class VelocityMessageFormatter

    @@ -161,37 +190,42 @@ extends co.aikar.commands.MessageFormatter<net.kyori.text.format.TextColor> +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    diff --git a/docs/acf-velocity/co/aikar/commands/VelocityRootCommand.html b/docs/acf-velocity/co/aikar/commands/VelocityRootCommand.html index 1e8a26e9..7473762c 100644 --- a/docs/acf-velocity/co/aikar/commands/VelocityRootCommand.html +++ b/docs/acf-velocity/co/aikar/commands/VelocityRootCommand.html @@ -1,12 +1,21 @@ - + - VelocityRootCommand (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands
    +

    Class VelocityRootCommand

    @@ -198,111 +232,112 @@ implements com.velocitypowered.api.command.Command, co.aikar.commands.RootComman
    • +
        -
      • +
      • Method Detail

        - + - +
        • addChild

          -
          public void addChild(co.aikar.commands.BaseCommand command)
          +
          public void addChild​(co.aikar.commands.BaseCommand command)
          Specified by:
          addChild in interface co.aikar.commands.RootCommand
        - +
        • getManager

          -
          public co.aikar.commands.CommandManager getManager()
          +
          public co.aikar.commands.CommandManager getManager()
          Specified by:
          getManager in interface co.aikar.commands.RootCommand
        - +
        • getSubCommands

          -
          public com.google.common.collect.SetMultimap<String,co.aikar.commands.RegisteredCommand> getSubCommands()
          +
          public com.google.common.collect.SetMultimap<String,​co.aikar.commands.RegisteredCommand> getSubCommands()
          Specified by:
          getSubCommands in interface co.aikar.commands.RootCommand
        - +
        • getChildren

          -
          public List<co.aikar.commands.BaseCommand> getChildren()
          +
          public List<co.aikar.commands.BaseCommand> getChildren()
          Specified by:
          getChildren in interface co.aikar.commands.RootCommand
        - +
        • execute

          -
          public void execute(com.velocitypowered.api.command.CommandSource source,
          -                    String[] args)
          +
          public void execute​(com.velocitypowered.api.command.CommandSource source,
          +                    String[] args)
          Specified by:
          execute in interface com.velocitypowered.api.command.Command
        - +
        • suggest

          -
          public List<Stringsuggest(com.velocitypowered.api.command.CommandSource source,
          -                            String[] args)
          +
          public List<Stringsuggest​(com.velocitypowered.api.command.CommandSource source,
          +                            String[] args)
          Specified by:
          suggest in interface com.velocitypowered.api.command.Command
        - +
        • getDefCommand

          -
          public co.aikar.commands.BaseCommand getDefCommand()
          +
          public co.aikar.commands.BaseCommand getDefCommand()
          Specified by:
          getDefCommand in interface co.aikar.commands.RootCommand
          @@ -311,21 +346,25 @@ implements com.velocitypowered.api.command.Command, co.aikar.commands.RootComman
      +
    +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    diff --git a/docs/acf-velocity/co/aikar/commands/class-use/ACFVelocityListener.html b/docs/acf-velocity/co/aikar/commands/class-use/ACFVelocityListener.html index 3ec26b4f..f5636d01 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/ACFVelocityListener.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/ACFVelocityListener.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ACFVelocityListener (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.ACFVelocityListener

    No usage of co.aikar.commands.ACFVelocityListener
    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/ACFVelocityUtil.html b/docs/acf-velocity/co/aikar/commands/class-use/ACFVelocityUtil.html index 19fe8ba9..3d1a8663 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/ACFVelocityUtil.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/ACFVelocityUtil.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.ACFVelocityUtil (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.ACFVelocityUtil

    No usage of co.aikar.commands.ACFVelocityUtil
    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/MinecraftMessageKeys.html b/docs/acf-velocity/co/aikar/commands/class-use/MinecraftMessageKeys.html index f5d1d49e..30f3ec97 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/MinecraftMessageKeys.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/MinecraftMessageKeys.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.MinecraftMessageKeys (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.MinecraftMessageKeys

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandCompletionContext.html b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandCompletionContext.html index 9b1e7e39..619ff177 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandCompletionContext.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandCompletionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.VelocityCommandCompletionContext (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.VelocityCommandCompletionContext

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandCompletions.html b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandCompletions.html index 1ad1ada3..8d002a0d 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandCompletions.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandCompletions.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.VelocityCommandCompletions (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.VelocityCommandCompletions

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandContexts.html b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandContexts.html index 879f6634..1fc343d4 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandContexts.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandContexts.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.VelocityCommandContexts (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.VelocityCommandContexts

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandExecutionContext.html b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandExecutionContext.html index b7b50309..a8763e47 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandExecutionContext.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandExecutionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.VelocityCommandExecutionContext (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.VelocityCommandExecutionContext

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandIssuer.html b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandIssuer.html index db11bdce..d6ad34ca 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandIssuer.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandIssuer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.VelocityCommandIssuer (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.VelocityCommandIssuer

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandManager.html b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandManager.html index 2b5459d7..2df26ecc 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandManager.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/VelocityCommandManager.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.VelocityCommandManager (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.VelocityCommandManager

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/VelocityConditionContext.html b/docs/acf-velocity/co/aikar/commands/class-use/VelocityConditionContext.html index ee295f7f..3e867ef2 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/VelocityConditionContext.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/VelocityConditionContext.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.VelocityConditionContext (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.VelocityConditionContext

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/VelocityLocales.html b/docs/acf-velocity/co/aikar/commands/class-use/VelocityLocales.html index e1dd7e76..85b3888b 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/VelocityLocales.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/VelocityLocales.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.VelocityLocales (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.VelocityLocales

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/VelocityMessageFormatter.html b/docs/acf-velocity/co/aikar/commands/class-use/VelocityMessageFormatter.html index 7c65df44..1d879028 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/VelocityMessageFormatter.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/VelocityMessageFormatter.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.VelocityMessageFormatter (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.VelocityMessageFormatter

    No usage of co.aikar.commands.VelocityMessageFormatter
    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/class-use/VelocityRootCommand.html b/docs/acf-velocity/co/aikar/commands/class-use/VelocityRootCommand.html index dd1b4336..c763953d 100644 --- a/docs/acf-velocity/co/aikar/commands/class-use/VelocityRootCommand.html +++ b/docs/acf-velocity/co/aikar/commands/class-use/VelocityRootCommand.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.VelocityRootCommand (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.VelocityRootCommand

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/contexts/OnlinePlayer.html b/docs/acf-velocity/co/aikar/commands/contexts/OnlinePlayer.html index 37b45680..07efeff0 100644 --- a/docs/acf-velocity/co/aikar/commands/contexts/OnlinePlayer.html +++ b/docs/acf-velocity/co/aikar/commands/contexts/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - OnlinePlayer (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands.contexts
    +

    Class OnlinePlayer

    @@ -120,61 +143,69 @@ extends
  • +
    +
    +
      -
    • +
    • Constructor Summary

      - +
      - + + - +
      Constructors 
      Constructor and DescriptionConstructorDescription
      OnlinePlayer(com.velocitypowered.api.proxy.Player player) -
      Deprecated. 
      +
      OnlinePlayer​(com.velocitypowered.api.proxy.Player player) +
      Deprecated.
       
    +
    +
    +
  • @@ -182,38 +213,43 @@ extends
  • +
      -
    • +
    • Constructor Detail

      - +
      • OnlinePlayer

        -
        public OnlinePlayer(com.velocitypowered.api.proxy.Player player)
        -
        Deprecated. 
        +
        public OnlinePlayer​(com.velocitypowered.api.proxy.Player player)
        +
        Deprecated.
    +
  • +
    + diff --git a/docs/acf-velocity/co/aikar/commands/contexts/class-use/OnlinePlayer.html b/docs/acf-velocity/co/aikar/commands/contexts/class-use/OnlinePlayer.html index 4316be54..4d455616 100644 --- a/docs/acf-velocity/co/aikar/commands/contexts/class-use/OnlinePlayer.html +++ b/docs/acf-velocity/co/aikar/commands/contexts/class-use/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.contexts.OnlinePlayer (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.contexts.OnlinePlayer

    No usage of co.aikar.commands.contexts.OnlinePlayer
    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/contexts/package-summary.html b/docs/acf-velocity/co/aikar/commands/contexts/package-summary.html index 7ab2c72e..58ef9817 100644 --- a/docs/acf-velocity/co/aikar/commands/contexts/package-summary.html +++ b/docs/acf-velocity/co/aikar/commands/contexts/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.contexts (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Package co.aikar.commands.contexts

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/velocity/contexts/OnlinePlayer.html b/docs/acf-velocity/co/aikar/commands/velocity/contexts/OnlinePlayer.html index 5508842e..c38fac24 100644 --- a/docs/acf-velocity/co/aikar/commands/velocity/contexts/OnlinePlayer.html +++ b/docs/acf-velocity/co/aikar/commands/velocity/contexts/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - OnlinePlayer (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +
    -
    co.aikar.commands.velocity.contexts
    +

    Class OnlinePlayer

    @@ -121,79 +144,94 @@ extends
  • +
      -
    • +
    • Field Summary

      - +
      - + + - + +
      Fields 
      Modifier and TypeField and DescriptionFieldDescription
      com.velocitypowered.api.proxy.Playerplayer player 
    +
    +
      -
    • +
    • Constructor Summary

      - +
      - + + - + +
      Constructors 
      Constructor and DescriptionConstructorDescription
      OnlinePlayer(com.velocitypowered.api.proxy.Player player) OnlinePlayer​(com.velocitypowered.api.proxy.Player player) 
    +
    +
    +
  • @@ -201,12 +239,13 @@ extends
  • +
      -
    • +
    • Field Detail

      - +
        @@ -217,94 +256,102 @@ extends
          -
        • +
        • Constructor Detail

          - +
          • OnlinePlayer

            -
            public OnlinePlayer(com.velocitypowered.api.proxy.Player player)
            +
            public OnlinePlayer​(com.velocitypowered.api.proxy.Player player)
        +
    +
    +
  • +
    + diff --git a/docs/acf-velocity/co/aikar/commands/velocity/contexts/class-use/OnlinePlayer.html b/docs/acf-velocity/co/aikar/commands/velocity/contexts/class-use/OnlinePlayer.html index 5cce9547..f0a2ee61 100644 --- a/docs/acf-velocity/co/aikar/commands/velocity/contexts/class-use/OnlinePlayer.html +++ b/docs/acf-velocity/co/aikar/commands/velocity/contexts/class-use/OnlinePlayer.html @@ -1,12 +1,21 @@ - + - Uses of Class co.aikar.commands.velocity.contexts.OnlinePlayer (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Uses of Class
    co.aikar.commands.velocity.contexts.OnlinePlayer

    +
    + diff --git a/docs/acf-velocity/co/aikar/commands/velocity/contexts/package-summary.html b/docs/acf-velocity/co/aikar/commands/velocity/contexts/package-summary.html index 43884a8f..2a4760b5 100644 --- a/docs/acf-velocity/co/aikar/commands/velocity/contexts/package-summary.html +++ b/docs/acf-velocity/co/aikar/commands/velocity/contexts/package-summary.html @@ -1,12 +1,21 @@ - + - co.aikar.commands.velocity.contexts (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "../../../../../"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Package co.aikar.commands.velocity.contexts

    +
    + diff --git a/docs/acf-velocity/constant-values.html b/docs/acf-velocity/constant-values.html index 97930cea..e02fa21d 100644 --- a/docs/acf-velocity/constant-values.html +++ b/docs/acf-velocity/constant-values.html @@ -1,12 +1,21 @@ - + - Constant Field Values (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Constant Field Values

    +

    Contents

    +
    +
    + diff --git a/docs/acf-velocity/deprecated-list.html b/docs/acf-velocity/deprecated-list.html index c43f9cd7..52dd8c1b 100644 --- a/docs/acf-velocity/deprecated-list.html +++ b/docs/acf-velocity/deprecated-list.html @@ -1,12 +1,21 @@ - + - Deprecated List (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Deprecated API

    Contents

    -
    +
    +
    +
    + +

    Copyright © 2020. All rights reserved.

    +
    + diff --git a/docs/acf-velocity/jquery/external/jquery/jquery.js b/docs/acf-velocity/jquery/external/jquery/jquery.js new file mode 100644 index 00000000..9b5206bc --- /dev/null +++ b/docs/acf-velocity/jquery/external/jquery/jquery.js @@ -0,0 +1,10364 @@ +/*! + * jQuery JavaScript Library v3.3.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2018-01-20T17:24Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + + + + var preservedScriptAttributes = { + type: true, + src: true, + noModule: true + }; + + function DOMEval( code, doc, node ) { + doc = doc || document; + + var i, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + if ( node[ i ] ) { + script[ i ] = node[ i ]; + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.3.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && Array.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( nodeName( elem, "iframe" ) ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
    " ], + col: [ 2, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + div.style.position = "absolute"; + scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a property mapped along what jQuery.cssProps suggests or to +// a vendor prefixed property. +function finalPropName( name ) { + var ret = jQuery.cssProps[ name ]; + if ( !ret ) { + ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + } + return ret; +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + ) ); + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + val = curCSS( elem, dimension, styles ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox; + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = valueIsBorderBox && + ( support.boxSizingReliable() || val === elem.style[ dimension ] ); + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + if ( val === "auto" || + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { + + val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; + + // offsetWidth/offsetHeight provide border-box values + valueIsBorderBox = true; + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra && boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ); + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && support.scrollboxSize() === styles.position ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = Date.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "\r\n"; + +// inject VBScript +document.write(IEBinaryToArray_ByteStr_Script); + +global.JSZipUtils._getBinaryFromXHR = function (xhr) { + var binary = xhr.responseBody; + var byteMapping = {}; + for ( var i = 0; i < 256; i++ ) { + for ( var j = 0; j < 256; j++ ) { + byteMapping[ String.fromCharCode( i + (j << 8) ) ] = + String.fromCharCode(i) + String.fromCharCode(j); + } + } + var rawBytes = IEBinaryToArray_ByteStr(binary); + var lastChr = IEBinaryToArray_ByteStr_Last(binary); + return rawBytes.replace(/[\s\S]/g, function( match ) { + return byteMapping[match]; + }) + lastChr; +}; + +// enforcing Stuk's coding style +// vim: set shiftwidth=4 softtabstop=4: + +},{}]},{},[1]) +; diff --git a/docs/acf-velocity/jquery/jszip-utils/dist/jszip-utils-ie.min.js b/docs/acf-velocity/jquery/jszip-utils/dist/jszip-utils-ie.min.js new file mode 100644 index 00000000..93d8bc8e --- /dev/null +++ b/docs/acf-velocity/jquery/jszip-utils/dist/jszip-utils-ie.min.js @@ -0,0 +1,10 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); diff --git a/docs/acf-velocity/jquery/jszip-utils/dist/jszip-utils.js b/docs/acf-velocity/jquery/jszip-utils/dist/jszip-utils.js new file mode 100644 index 00000000..775895ec --- /dev/null +++ b/docs/acf-velocity/jquery/jszip-utils/dist/jszip-utils.js @@ -0,0 +1,118 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ + +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64; + enc4 = remainingBytes > 2 ? (chr3 & 63) : 64; + + output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4)); + + } + + return output.join(""); +}; + +// public method for decoding +exports.decode = function(input) { + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0, resultIndex = 0; + + var dataUrlPrefix = "data:"; + + if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) { + // This is a common error: people give a data url + // (data:image/png;base64,iVBOR...) with a {base64: true} and + // wonders why things don't work. + // We can detect that the string input looks like a data url but we + // *can't* be sure it is one: removing everything up to the comma would + // be too dangerous. + throw new Error("Invalid base64 input, it looks like a data url."); + } + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + var totalLength = input.length * 3 / 4; + if(input.charAt(input.length - 1) === _keyStr.charAt(64)) { + totalLength--; + } + if(input.charAt(input.length - 2) === _keyStr.charAt(64)) { + totalLength--; + } + if (totalLength % 1 !== 0) { + // totalLength is not an integer, the length does not match a valid + // base64 content. That can happen if: + // - the input is not a base64 content + // - the input is *almost* a base64 content, with a extra chars at the + // beginning or at the end + // - the input uses a base64 variant (base64url for example) + throw new Error("Invalid base64 input, bad content length."); + } + var output; + if (support.uint8array) { + output = new Uint8Array(totalLength|0); + } else { + output = new Array(totalLength|0); + } + + while (i < input.length) { + + enc1 = _keyStr.indexOf(input.charAt(i++)); + enc2 = _keyStr.indexOf(input.charAt(i++)); + enc3 = _keyStr.indexOf(input.charAt(i++)); + enc4 = _keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output[resultIndex++] = chr1; + + if (enc3 !== 64) { + output[resultIndex++] = chr2; + } + if (enc4 !== 64) { + output[resultIndex++] = chr3; + } + + } + + return output; +}; + +},{"./support":30,"./utils":32}],2:[function(require,module,exports){ +'use strict'; + +var external = require("./external"); +var DataWorker = require('./stream/DataWorker'); +var DataLengthProbe = require('./stream/DataLengthProbe'); +var Crc32Probe = require('./stream/Crc32Probe'); +var DataLengthProbe = require('./stream/DataLengthProbe'); + +/** + * Represent a compressed object, with everything needed to decompress it. + * @constructor + * @param {number} compressedSize the size of the data compressed. + * @param {number} uncompressedSize the size of the data after decompression. + * @param {number} crc32 the crc32 of the decompressed file. + * @param {object} compression the type of compression, see lib/compressions.js. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data. + */ +function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) { + this.compressedSize = compressedSize; + this.uncompressedSize = uncompressedSize; + this.crc32 = crc32; + this.compression = compression; + this.compressedContent = data; +} + +CompressedObject.prototype = { + /** + * Create a worker to get the uncompressed content. + * @return {GenericWorker} the worker. + */ + getContentWorker : function () { + var worker = new DataWorker(external.Promise.resolve(this.compressedContent)) + .pipe(this.compression.uncompressWorker()) + .pipe(new DataLengthProbe("data_length")); + + var that = this; + worker.on("end", function () { + if(this.streamInfo['data_length'] !== that.uncompressedSize) { + throw new Error("Bug : uncompressed data size mismatch"); + } + }); + return worker; + }, + /** + * Create a worker to get the compressed content. + * @return {GenericWorker} the worker. + */ + getCompressedWorker : function () { + return new DataWorker(external.Promise.resolve(this.compressedContent)) + .withStreamInfo("compressedSize", this.compressedSize) + .withStreamInfo("uncompressedSize", this.uncompressedSize) + .withStreamInfo("crc32", this.crc32) + .withStreamInfo("compression", this.compression) + ; + } +}; + +/** + * Chain the given worker with other workers to compress the content with the + * given compresion. + * @param {GenericWorker} uncompressedWorker the worker to pipe. + * @param {Object} compression the compression object. + * @param {Object} compressionOptions the options to use when compressing. + * @return {GenericWorker} the new worker compressing the content. + */ +CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions) { + return uncompressedWorker + .pipe(new Crc32Probe()) + .pipe(new DataLengthProbe("uncompressedSize")) + .pipe(compression.compressWorker(compressionOptions)) + .pipe(new DataLengthProbe("compressedSize")) + .withStreamInfo("compression", compression); +}; + +module.exports = CompressedObject; + +},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require("./stream/GenericWorker"); + +exports.STORE = { + magic: "\x00\x00", + compressWorker : function (compressionOptions) { + return new GenericWorker("STORE compression"); + }, + uncompressWorker : function () { + return new GenericWorker("STORE decompression"); + } +}; +exports.DEFLATE = require('./flate'); + +},{"./flate":7,"./stream/GenericWorker":28}],4:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); + +/** + * The following functions come from pako, from pako/lib/zlib/crc32.js + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +// That's all for the pako functions. + +/** + * Compute the crc32 of a string. + * This is almost the same as the function crc32, but for strings. Using the + * same function for the two use cases leads to horrible performances. + * @param {Number} crc the starting value of the crc. + * @param {String} str the string to use. + * @param {Number} len the length of the string. + * @param {Number} pos the starting position for the crc32 computation. + * @return {Number} the computed crc32. + */ +function crc32str(crc, str, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +module.exports = function crc32wrapper(input, crc) { + if (typeof input === "undefined" || !input.length) { + return 0; + } + + var isArray = utils.getTypeOf(input) !== "string"; + + if(isArray) { + return crc32(crc|0, input, input.length, 0); + } else { + return crc32str(crc|0, input, input.length, 0); + } +}; + +},{"./utils":32}],5:[function(require,module,exports){ +'use strict'; +exports.base64 = false; +exports.binary = false; +exports.dir = false; +exports.createFolders = true; +exports.date = null; +exports.compression = null; +exports.compressionOptions = null; +exports.comment = null; +exports.unixPermissions = null; +exports.dosPermissions = null; + +},{}],6:[function(require,module,exports){ +/* global Promise */ +'use strict'; + +// load the global object first: +// - it should be better integrated in the system (unhandledRejection in node) +// - the environment may have a custom Promise implementation (see zone.js) +var ES6Promise = null; +if (typeof Promise !== "undefined") { + ES6Promise = Promise; +} else { + ES6Promise = require("lie"); +} + +/** + * Let the user use/change some implementations. + */ +module.exports = { + Promise: ES6Promise +}; + +},{"lie":58}],7:[function(require,module,exports){ +'use strict'; +var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); + +var pako = require("pako"); +var utils = require("./utils"); +var GenericWorker = require("./stream/GenericWorker"); + +var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array"; + +exports.magic = "\x08\x00"; + +/** + * Create a worker that uses pako to inflate/deflate. + * @constructor + * @param {String} action the name of the pako function to call : either "Deflate" or "Inflate". + * @param {Object} options the options to use when (de)compressing. + */ +function FlateWorker(action, options) { + GenericWorker.call(this, "FlateWorker/" + action); + + this._pako = null; + this._pakoAction = action; + this._pakoOptions = options; + // the `meta` object from the last chunk received + // this allow this worker to pass around metadata + this.meta = {}; +} + +utils.inherits(FlateWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +FlateWorker.prototype.processChunk = function (chunk) { + this.meta = chunk.meta; + if (this._pako === null) { + this._createPako(); + } + this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false); +}; + +/** + * @see GenericWorker.flush + */ +FlateWorker.prototype.flush = function () { + GenericWorker.prototype.flush.call(this); + if (this._pako === null) { + this._createPako(); + } + this._pako.push([], true); +}; +/** + * @see GenericWorker.cleanUp + */ +FlateWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this._pako = null; +}; + +/** + * Create the _pako object. + * TODO: lazy-loading this object isn't the best solution but it's the + * quickest. The best solution is to lazy-load the worker list. See also the + * issue #446. + */ +FlateWorker.prototype._createPako = function () { + this._pako = new pako[this._pakoAction]({ + raw: true, + level: this._pakoOptions.level || -1 // default compression + }); + var self = this; + this._pako.onData = function(data) { + self.push({ + data : data, + meta : self.meta + }); + }; +}; + +exports.compressWorker = function (compressionOptions) { + return new FlateWorker("Deflate", compressionOptions); +}; +exports.uncompressWorker = function () { + return new FlateWorker("Inflate", {}); +}; + +},{"./stream/GenericWorker":28,"./utils":32,"pako":59}],8:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); +var utf8 = require('../utf8'); +var crc32 = require('../crc32'); +var signature = require('../signature'); + +/** + * Transform an integer into a string in hexadecimal. + * @private + * @param {number} dec the number to convert. + * @param {number} bytes the number of bytes to generate. + * @returns {string} the result. + */ +var decToHex = function(dec, bytes) { + var hex = "", i; + for (i = 0; i < bytes; i++) { + hex += String.fromCharCode(dec & 0xff); + dec = dec >>> 8; + } + return hex; +}; + +/** + * Generate the UNIX part of the external file attributes. + * @param {Object} unixPermissions the unix permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : + * + * TTTTsstrwxrwxrwx0000000000ADVSHR + * ^^^^____________________________ file type, see zipinfo.c (UNX_*) + * ^^^_________________________ setuid, setgid, sticky + * ^^^^^^^^^________________ permissions + * ^^^^^^^^^^______ not used ? + * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only + */ +var generateUnixExternalFileAttr = function (unixPermissions, isDir) { + + var result = unixPermissions; + if (!unixPermissions) { + // I can't use octal values in strict mode, hence the hexa. + // 040775 => 0x41fd + // 0100664 => 0x81b4 + result = isDir ? 0x41fd : 0x81b4; + } + return (result & 0xFFFF) << 16; +}; + +/** + * Generate the DOS part of the external file attributes. + * @param {Object} dosPermissions the dos permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * Bit 0 Read-Only + * Bit 1 Hidden + * Bit 2 System + * Bit 3 Volume Label + * Bit 4 Directory + * Bit 5 Archive + */ +var generateDosExternalFileAttr = function (dosPermissions, isDir) { + + // the dir flag is already set for compatibility + return (dosPermissions || 0) & 0x3F; +}; + +/** + * Generate the various parts used in the construction of the final zip file. + * @param {Object} streamInfo the hash with informations about the compressed file. + * @param {Boolean} streamedContent is the content streamed ? + * @param {Boolean} streamingEnded is the stream finished ? + * @param {number} offset the current offset from the start of the zip file. + * @param {String} platform let's pretend we are this platform (change platform dependents fields) + * @param {Function} encodeFileName the function to encode the file name / comment. + * @return {Object} the zip parts. + */ +var generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) { + var file = streamInfo['file'], + compression = streamInfo['compression'], + useCustomEncoding = encodeFileName !== utf8.utf8encode, + encodedFileName = utils.transformTo("string", encodeFileName(file.name)), + utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), + comment = file.comment, + encodedComment = utils.transformTo("string", encodeFileName(comment)), + utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), + useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, + useUTF8ForComment = utfEncodedComment.length !== comment.length, + dosTime, + dosDate, + extraFields = "", + unicodePathExtraField = "", + unicodeCommentExtraField = "", + dir = file.dir, + date = file.date; + + + var dataInfo = { + crc32 : 0, + compressedSize : 0, + uncompressedSize : 0 + }; + + // if the content is streamed, the sizes/crc32 are only available AFTER + // the end of the stream. + if (!streamedContent || streamingEnded) { + dataInfo.crc32 = streamInfo['crc32']; + dataInfo.compressedSize = streamInfo['compressedSize']; + dataInfo.uncompressedSize = streamInfo['uncompressedSize']; + } + + var bitflag = 0; + if (streamedContent) { + // Bit 3: the sizes/crc32 are set to zero in the local header. + // The correct values are put in the data descriptor immediately + // following the compressed data. + bitflag |= 0x0008; + } + if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) { + // Bit 11: Language encoding flag (EFS). + bitflag |= 0x0800; + } + + + var extFileAttr = 0; + var versionMadeBy = 0; + if (dir) { + // dos or unix, we set the dos dir flag + extFileAttr |= 0x00010; + } + if(platform === "UNIX") { + versionMadeBy = 0x031E; // UNIX, version 3.0 + extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); + } else { // DOS or other, fallback to DOS + versionMadeBy = 0x0014; // DOS, version 2.0 + extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); + } + + // date + // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html + + dosTime = date.getUTCHours(); + dosTime = dosTime << 6; + dosTime = dosTime | date.getUTCMinutes(); + dosTime = dosTime << 5; + dosTime = dosTime | date.getUTCSeconds() / 2; + + dosDate = date.getUTCFullYear() - 1980; + dosDate = dosDate << 4; + dosDate = dosDate | (date.getUTCMonth() + 1); + dosDate = dosDate << 5; + dosDate = dosDate | date.getUTCDate(); + + if (useUTF8ForFileName) { + // set the unicode path extra field. unzip needs at least one extra + // field to correctly handle unicode path, so using the path is as good + // as any other information. This could improve the situation with + // other archive managers too. + // This field is usually used without the utf8 flag, with a non + // unicode path in the header (winrar, winzip). This helps (a bit) + // with the messy Windows' default compressed folders feature but + // breaks on p7zip which doesn't seek the unicode path extra field. + // So for now, UTF-8 everywhere ! + unicodePathExtraField = + // Version + decToHex(1, 1) + + // NameCRC32 + decToHex(crc32(encodedFileName), 4) + + // UnicodeName + utfEncodedFileName; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x70" + + // size + decToHex(unicodePathExtraField.length, 2) + + // content + unicodePathExtraField; + } + + if(useUTF8ForComment) { + + unicodeCommentExtraField = + // Version + decToHex(1, 1) + + // CommentCRC32 + decToHex(crc32(encodedComment), 4) + + // UnicodeName + utfEncodedComment; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x63" + + // size + decToHex(unicodeCommentExtraField.length, 2) + + // content + unicodeCommentExtraField; + } + + var header = ""; + + // version needed to extract + header += "\x0A\x00"; + // general purpose bit flag + header += decToHex(bitflag, 2); + // compression method + header += compression.magic; + // last mod file time + header += decToHex(dosTime, 2); + // last mod file date + header += decToHex(dosDate, 2); + // crc-32 + header += decToHex(dataInfo.crc32, 4); + // compressed size + header += decToHex(dataInfo.compressedSize, 4); + // uncompressed size + header += decToHex(dataInfo.uncompressedSize, 4); + // file name length + header += decToHex(encodedFileName.length, 2); + // extra field length + header += decToHex(extraFields.length, 2); + + + var fileRecord = signature.LOCAL_FILE_HEADER + header + encodedFileName + extraFields; + + var dirRecord = signature.CENTRAL_FILE_HEADER + + // version made by (00: DOS) + decToHex(versionMadeBy, 2) + + // file header (common to file and central directory) + header + + // file comment length + decToHex(encodedComment.length, 2) + + // disk number start + "\x00\x00" + + // internal file attributes TODO + "\x00\x00" + + // external file attributes + decToHex(extFileAttr, 4) + + // relative offset of local header + decToHex(offset, 4) + + // file name + encodedFileName + + // extra field + extraFields + + // file comment + encodedComment; + + return { + fileRecord: fileRecord, + dirRecord: dirRecord + }; +}; + +/** + * Generate the EOCD record. + * @param {Number} entriesCount the number of entries in the zip file. + * @param {Number} centralDirLength the length (in bytes) of the central dir. + * @param {Number} localDirLength the length (in bytes) of the local dir. + * @param {String} comment the zip file comment as a binary string. + * @param {Function} encodeFileName the function to encode the comment. + * @return {String} the EOCD record. + */ +var generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) { + var dirEnd = ""; + var encodedComment = utils.transformTo("string", encodeFileName(comment)); + + // end of central dir signature + dirEnd = signature.CENTRAL_DIRECTORY_END + + // number of this disk + "\x00\x00" + + // number of the disk with the start of the central directory + "\x00\x00" + + // total number of entries in the central directory on this disk + decToHex(entriesCount, 2) + + // total number of entries in the central directory + decToHex(entriesCount, 2) + + // size of the central directory 4 bytes + decToHex(centralDirLength, 4) + + // offset of start of central directory with respect to the starting disk number + decToHex(localDirLength, 4) + + // .ZIP file comment length + decToHex(encodedComment.length, 2) + + // .ZIP file comment + encodedComment; + + return dirEnd; +}; + +/** + * Generate data descriptors for a file entry. + * @param {Object} streamInfo the hash generated by a worker, containing informations + * on the file entry. + * @return {String} the data descriptors. + */ +var generateDataDescriptors = function (streamInfo) { + var descriptor = ""; + descriptor = signature.DATA_DESCRIPTOR + + // crc-32 4 bytes + decToHex(streamInfo['crc32'], 4) + + // compressed size 4 bytes + decToHex(streamInfo['compressedSize'], 4) + + // uncompressed size 4 bytes + decToHex(streamInfo['uncompressedSize'], 4); + + return descriptor; +}; + + +/** + * A worker to concatenate other workers to create a zip file. + * @param {Boolean} streamFiles `true` to stream the content of the files, + * `false` to accumulate it. + * @param {String} comment the comment to use. + * @param {String} platform the platform to use, "UNIX" or "DOS". + * @param {Function} encodeFileName the function to encode file names and comments. + */ +function ZipFileWorker(streamFiles, comment, platform, encodeFileName) { + GenericWorker.call(this, "ZipFileWorker"); + // The number of bytes written so far. This doesn't count accumulated chunks. + this.bytesWritten = 0; + // The comment of the zip file + this.zipComment = comment; + // The platform "generating" the zip file. + this.zipPlatform = platform; + // the function to encode file names and comments. + this.encodeFileName = encodeFileName; + // Should we stream the content of the files ? + this.streamFiles = streamFiles; + // If `streamFiles` is false, we will need to accumulate the content of the + // files to calculate sizes / crc32 (and write them *before* the content). + // This boolean indicates if we are accumulating chunks (it will change a lot + // during the lifetime of this worker). + this.accumulate = false; + // The buffer receiving chunks when accumulating content. + this.contentBuffer = []; + // The list of generated directory records. + this.dirRecords = []; + // The offset (in bytes) from the beginning of the zip file for the current source. + this.currentSourceOffset = 0; + // The total number of entries in this zip file. + this.entriesCount = 0; + // the name of the file currently being added, null when handling the end of the zip file. + // Used for the emited metadata. + this.currentFile = null; + + + + this._sources = []; +} +utils.inherits(ZipFileWorker, GenericWorker); + +/** + * @see GenericWorker.push + */ +ZipFileWorker.prototype.push = function (chunk) { + + var currentFilePercent = chunk.meta.percent || 0; + var entriesCount = this.entriesCount; + var remainingFiles = this._sources.length; + + if(this.accumulate) { + this.contentBuffer.push(chunk); + } else { + this.bytesWritten += chunk.data.length; + + GenericWorker.prototype.push.call(this, { + data : chunk.data, + meta : { + currentFile : this.currentFile, + percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100 + } + }); + } +}; + +/** + * The worker started a new source (an other worker). + * @param {Object} streamInfo the streamInfo object from the new source. + */ +ZipFileWorker.prototype.openedSource = function (streamInfo) { + this.currentSourceOffset = this.bytesWritten; + this.currentFile = streamInfo['file'].name; + + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + + // don't stream folders (because they don't have any content) + if(streamedContent) { + var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + } else { + // we need to wait for the whole file before pushing anything + this.accumulate = true; + } +}; + +/** + * The worker finished a source (an other worker). + * @param {Object} streamInfo the streamInfo object from the finished source. + */ +ZipFileWorker.prototype.closedSource = function (streamInfo) { + this.accumulate = false; + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + + this.dirRecords.push(record.dirRecord); + if(streamedContent) { + // after the streamed file, we put data descriptors + this.push({ + data : generateDataDescriptors(streamInfo), + meta : {percent:100} + }); + } else { + // the content wasn't streamed, we need to push everything now + // first the file record, then the content + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + while(this.contentBuffer.length) { + this.push(this.contentBuffer.shift()); + } + } + this.currentFile = null; +}; + +/** + * @see GenericWorker.flush + */ +ZipFileWorker.prototype.flush = function () { + + var localDirLength = this.bytesWritten; + for(var i = 0; i < this.dirRecords.length; i++) { + this.push({ + data : this.dirRecords[i], + meta : {percent:100} + }); + } + var centralDirLength = this.bytesWritten - localDirLength; + + var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName); + + this.push({ + data : dirEnd, + meta : {percent:100} + }); +}; + +/** + * Prepare the next source to be read. + */ +ZipFileWorker.prototype.prepareNextSource = function () { + this.previous = this._sources.shift(); + this.openedSource(this.previous.streamInfo); + if (this.isPaused) { + this.previous.pause(); + } else { + this.previous.resume(); + } +}; + +/** + * @see GenericWorker.registerPrevious + */ +ZipFileWorker.prototype.registerPrevious = function (previous) { + this._sources.push(previous); + var self = this; + + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.closedSource(self.previous.streamInfo); + if(self._sources.length) { + self.prepareNextSource(); + } else { + self.end(); + } + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; +}; + +/** + * @see GenericWorker.resume + */ +ZipFileWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this.previous && this._sources.length) { + this.prepareNextSource(); + return true; + } + if (!this.previous && !this._sources.length && !this.generatedError) { + this.end(); + return true; + } +}; + +/** + * @see GenericWorker.error + */ +ZipFileWorker.prototype.error = function (e) { + var sources = this._sources; + if(!GenericWorker.prototype.error.call(this, e)) { + return false; + } + for(var i = 0; i < sources.length; i++) { + try { + sources[i].error(e); + } catch(e) { + // the `error` exploded, nothing to do + } + } + return true; +}; + +/** + * @see GenericWorker.lock + */ +ZipFileWorker.prototype.lock = function () { + GenericWorker.prototype.lock.call(this); + var sources = this._sources; + for(var i = 0; i < sources.length; i++) { + sources[i].lock(); + } +}; + +module.exports = ZipFileWorker; + +},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(require,module,exports){ +'use strict'; + +var compressions = require('../compressions'); +var ZipFileWorker = require('./ZipFileWorker'); + +/** + * Find the compression to use. + * @param {String} fileCompression the compression defined at the file level, if any. + * @param {String} zipCompression the compression defined at the load() level. + * @return {Object} the compression object to use. + */ +var getCompression = function (fileCompression, zipCompression) { + + var compressionName = fileCompression || zipCompression; + var compression = compressions[compressionName]; + if (!compression) { + throw new Error(compressionName + " is not a valid compression method !"); + } + return compression; +}; + +/** + * Create a worker to generate a zip file. + * @param {JSZip} zip the JSZip instance at the right root level. + * @param {Object} options to generate the zip file. + * @param {String} comment the comment to use. + */ +exports.generateWorker = function (zip, options, comment) { + + var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName); + var entriesCount = 0; + try { + + zip.forEach(function (relativePath, file) { + entriesCount++; + var compression = getCompression(file.options.compression, options.compression); + var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; + var dir = file.dir, date = file.date; + + file._compressWorker(compression, compressionOptions) + .withStreamInfo("file", { + name : relativePath, + dir : dir, + date : date, + comment : file.comment || "", + unixPermissions : file.unixPermissions, + dosPermissions : file.dosPermissions + }) + .pipe(zipFileWorker); + }); + zipFileWorker.entriesCount = entriesCount; + } catch (e) { + zipFileWorker.error(e); + } + + return zipFileWorker; +}; + +},{"../compressions":3,"./ZipFileWorker":8}],10:[function(require,module,exports){ +'use strict'; + +/** + * Representation a of zip file in js + * @constructor + */ +function JSZip() { + // if this constructor is used without `new`, it adds `new` before itself: + if(!(this instanceof JSZip)) { + return new JSZip(); + } + + if(arguments.length) { + throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); + } + + // object containing the files : + // { + // "folder/" : {...}, + // "folder/data.txt" : {...} + // } + this.files = {}; + + this.comment = null; + + // Where we are in the hierarchy + this.root = ""; + this.clone = function() { + var newObj = new JSZip(); + for (var i in this) { + if (typeof this[i] !== "function") { + newObj[i] = this[i]; + } + } + return newObj; + }; +} +JSZip.prototype = require('./object'); +JSZip.prototype.loadAsync = require('./load'); +JSZip.support = require('./support'); +JSZip.defaults = require('./defaults'); + +// TODO find a better way to handle this version, +// a require('package.json').version doesn't work with webpack, see #327 +JSZip.version = "3.1.5"; + +JSZip.loadAsync = function (content, options) { + return new JSZip().loadAsync(content, options); +}; + +JSZip.external = require("./external"); +module.exports = JSZip; + +},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(require,module,exports){ +'use strict'; +var utils = require('./utils'); +var external = require("./external"); +var utf8 = require('./utf8'); +var utils = require('./utils'); +var ZipEntries = require('./zipEntries'); +var Crc32Probe = require('./stream/Crc32Probe'); +var nodejsUtils = require("./nodejsUtils"); + +/** + * Check the CRC32 of an entry. + * @param {ZipEntry} zipEntry the zip entry to check. + * @return {Promise} the result. + */ +function checkEntryCRC32(zipEntry) { + return new external.Promise(function (resolve, reject) { + var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe()); + worker.on("error", function (e) { + reject(e); + }) + .on("end", function () { + if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) { + reject(new Error("Corrupted zip : CRC32 mismatch")); + } else { + resolve(); + } + }) + .resume(); + }); +} + +module.exports = function(data, options) { + var zip = this; + options = utils.extend(options || {}, { + base64: false, + checkCRC32: false, + optimizedBinaryString: false, + createFolders: false, + decodeFileName: utf8.utf8decode + }); + + if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + return external.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")); + } + + return utils.prepareContent("the loaded zip file", data, true, options.optimizedBinaryString, options.base64) + .then(function(data) { + var zipEntries = new ZipEntries(options); + zipEntries.load(data); + return zipEntries; + }).then(function checkCRC32(zipEntries) { + var promises = [external.Promise.resolve(zipEntries)]; + var files = zipEntries.files; + if (options.checkCRC32) { + for (var i = 0; i < files.length; i++) { + promises.push(checkEntryCRC32(files[i])); + } + } + return external.Promise.all(promises); + }).then(function addFiles(results) { + var zipEntries = results.shift(); + var files = zipEntries.files; + for (var i = 0; i < files.length; i++) { + var input = files[i]; + zip.file(input.fileNameStr, input.decompressed, { + binary: true, + optimizedBinaryString: true, + date: input.date, + dir: input.dir, + comment : input.fileCommentStr.length ? input.fileCommentStr : null, + unixPermissions : input.unixPermissions, + dosPermissions : input.dosPermissions, + createFolders: options.createFolders + }); + } + if (zipEntries.zipComment.length) { + zip.comment = zipEntries.zipComment; + } + + return zip; + }); +}; + +},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(require,module,exports){ +"use strict"; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); + +/** + * A worker that use a nodejs stream as source. + * @constructor + * @param {String} filename the name of the file entry for this stream. + * @param {Readable} stream the nodejs stream. + */ +function NodejsStreamInputAdapter(filename, stream) { + GenericWorker.call(this, "Nodejs stream input adapter for " + filename); + this._upstreamEnded = false; + this._bindStream(stream); +} + +utils.inherits(NodejsStreamInputAdapter, GenericWorker); + +/** + * Prepare the stream and bind the callbacks on it. + * Do this ASAP on node 0.10 ! A lazy binding doesn't always work. + * @param {Stream} stream the nodejs stream to use. + */ +NodejsStreamInputAdapter.prototype._bindStream = function (stream) { + var self = this; + this._stream = stream; + stream.pause(); + stream + .on("data", function (chunk) { + self.push({ + data: chunk, + meta : { + percent : 0 + } + }); + }) + .on("error", function (e) { + if(self.isPaused) { + this.generatedError = e; + } else { + self.error(e); + } + }) + .on("end", function () { + if(self.isPaused) { + self._upstreamEnded = true; + } else { + self.end(); + } + }); +}; +NodejsStreamInputAdapter.prototype.pause = function () { + if(!GenericWorker.prototype.pause.call(this)) { + return false; + } + this._stream.pause(); + return true; +}; +NodejsStreamInputAdapter.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if(this._upstreamEnded) { + this.end(); + } else { + this._stream.resume(); + } + + return true; +}; + +module.exports = NodejsStreamInputAdapter; + +},{"../stream/GenericWorker":28,"../utils":32}],13:[function(require,module,exports){ +'use strict'; + +var Readable = require('readable-stream').Readable; + +var utils = require('../utils'); +utils.inherits(NodejsStreamOutputAdapter, Readable); + +/** +* A nodejs stream using a worker as source. +* @see the SourceWrapper in http://nodejs.org/api/stream.html +* @constructor +* @param {StreamHelper} helper the helper wrapping the worker +* @param {Object} options the nodejs stream options +* @param {Function} updateCb the update callback. +*/ +function NodejsStreamOutputAdapter(helper, options, updateCb) { + Readable.call(this, options); + this._helper = helper; + + var self = this; + helper.on("data", function (data, meta) { + if (!self.push(data)) { + self._helper.pause(); + } + if(updateCb) { + updateCb(meta); + } + }) + .on("error", function(e) { + self.emit('error', e); + }) + .on("end", function () { + self.push(null); + }); +} + + +NodejsStreamOutputAdapter.prototype._read = function() { + this._helper.resume(); +}; + +module.exports = NodejsStreamOutputAdapter; + +},{"../utils":32,"readable-stream":16}],14:[function(require,module,exports){ +'use strict'; + +module.exports = { + /** + * True if this is running in Nodejs, will be undefined in a browser. + * In a browser, browserify won't include this file and the whole module + * will be resolved an empty object. + */ + isNode : typeof Buffer !== "undefined", + /** + * Create a new nodejs Buffer from an existing content. + * @param {Object} data the data to pass to the constructor. + * @param {String} encoding the encoding to use. + * @return {Buffer} a new Buffer. + */ + newBufferFrom: function(data, encoding) { + // XXX We can't use `Buffer.from` which comes from `Uint8Array.from` + // in nodejs v4 (< v.4.5). It's not the expected implementation (and + // has a different signature). + // see https://github.com/nodejs/node/issues/8053 + // A condition on nodejs' version won't solve the issue as we don't + // control the Buffer polyfills that may or may not be used. + return new Buffer(data, encoding); + }, + /** + * Create a new nodejs Buffer with the specified size. + * @param {Integer} size the size of the buffer. + * @return {Buffer} a new Buffer. + */ + allocBuffer: function (size) { + if (Buffer.alloc) { + return Buffer.alloc(size); + } else { + return new Buffer(size); + } + }, + /** + * Find out if an object is a Buffer. + * @param {Object} b the object to test. + * @return {Boolean} true if the object is a Buffer, false otherwise. + */ + isBuffer : function(b){ + return Buffer.isBuffer(b); + }, + + isStream : function (obj) { + return obj && + typeof obj.on === "function" && + typeof obj.pause === "function" && + typeof obj.resume === "function"; + } +}; + +},{}],15:[function(require,module,exports){ +'use strict'; +var utf8 = require('./utf8'); +var utils = require('./utils'); +var GenericWorker = require('./stream/GenericWorker'); +var StreamHelper = require('./stream/StreamHelper'); +var defaults = require('./defaults'); +var CompressedObject = require('./compressedObject'); +var ZipObject = require('./zipObject'); +var generate = require("./generate"); +var nodejsUtils = require("./nodejsUtils"); +var NodejsStreamInputAdapter = require("./nodejs/NodejsStreamInputAdapter"); + + +/** + * Add a file in the current folder. + * @private + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file + * @param {Object} originalOptions the options of the file + * @return {Object} the new file. + */ +var fileAdd = function(name, data, originalOptions) { + // be sure sub folders exist + var dataType = utils.getTypeOf(data), + parent; + + + /* + * Correct options. + */ + + var o = utils.extend(originalOptions || {}, defaults); + o.date = o.date || new Date(); + if (o.compression !== null) { + o.compression = o.compression.toUpperCase(); + } + + if (typeof o.unixPermissions === "string") { + o.unixPermissions = parseInt(o.unixPermissions, 8); + } + + // UNX_IFDIR 0040000 see zipinfo.c + if (o.unixPermissions && (o.unixPermissions & 0x4000)) { + o.dir = true; + } + // Bit 4 Directory + if (o.dosPermissions && (o.dosPermissions & 0x0010)) { + o.dir = true; + } + + if (o.dir) { + name = forceTrailingSlash(name); + } + if (o.createFolders && (parent = parentFolder(name))) { + folderAdd.call(this, parent, true); + } + + var isUnicodeString = dataType === "string" && o.binary === false && o.base64 === false; + if (!originalOptions || typeof originalOptions.binary === "undefined") { + o.binary = !isUnicodeString; + } + + + var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0; + + if (isCompressedEmpty || o.dir || !data || data.length === 0) { + o.base64 = false; + o.binary = true; + data = ""; + o.compression = "STORE"; + dataType = "string"; + } + + /* + * Convert content to fit. + */ + + var zipObjectContent = null; + if (data instanceof CompressedObject || data instanceof GenericWorker) { + zipObjectContent = data; + } else if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + zipObjectContent = new NodejsStreamInputAdapter(name, data); + } else { + zipObjectContent = utils.prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64); + } + + var object = new ZipObject(name, zipObjectContent, o); + this.files[name] = object; + /* + TODO: we can't throw an exception because we have async promises + (we can have a promise of a Date() for example) but returning a + promise is useless because file(name, data) returns the JSZip + object for chaining. Should we break that to allow the user + to catch the error ? + + return external.Promise.resolve(zipObjectContent) + .then(function () { + return object; + }); + */ +}; + +/** + * Find the parent folder of the path. + * @private + * @param {string} path the path to use + * @return {string} the parent folder, or "" + */ +var parentFolder = function (path) { + if (path.slice(-1) === '/') { + path = path.substring(0, path.length - 1); + } + var lastSlash = path.lastIndexOf('/'); + return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; +}; + +/** + * Returns the path with a slash at the end. + * @private + * @param {String} path the path to check. + * @return {String} the path with a trailing slash. + */ +var forceTrailingSlash = function(path) { + // Check the name ends with a / + if (path.slice(-1) !== "/") { + path += "/"; // IE doesn't like substr(-1) + } + return path; +}; + +/** + * Add a (sub) folder in the current folder. + * @private + * @param {string} name the folder's name + * @param {boolean=} [createFolders] If true, automatically create sub + * folders. Defaults to false. + * @return {Object} the new folder. + */ +var folderAdd = function(name, createFolders) { + createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders; + + name = forceTrailingSlash(name); + + // Does this folder already exist? + if (!this.files[name]) { + fileAdd.call(this, name, null, { + dir: true, + createFolders: createFolders + }); + } + return this.files[name]; +}; + +/** +* Cross-window, cross-Node-context regular expression detection +* @param {Object} object Anything +* @return {Boolean} true if the object is a regular expression, +* false otherwise +*/ +function isRegExp(object) { + return Object.prototype.toString.call(object) === "[object RegExp]"; +} + +// return the actual prototype of JSZip +var out = { + /** + * @see loadAsync + */ + load: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + + /** + * Call a callback function for each entry at this folder level. + * @param {Function} cb the callback function: + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + */ + forEach: function(cb) { + var filename, relativePath, file; + for (filename in this.files) { + if (!this.files.hasOwnProperty(filename)) { + continue; + } + file = this.files[filename]; + relativePath = filename.slice(this.root.length, filename.length); + if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root + cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn... + } + } + }, + + /** + * Filter nested files/folders with the specified function. + * @param {Function} search the predicate to use : + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + * @return {Array} An array of matching elements. + */ + filter: function(search) { + var result = []; + this.forEach(function (relativePath, entry) { + if (search(relativePath, entry)) { // the file matches the function + result.push(entry); + } + + }); + return result; + }, + + /** + * Add a file to the zip file, or search a file. + * @param {string|RegExp} name The name of the file to add (if data is defined), + * the name of the file to find (if no data) or a regex to match files. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded + * @param {Object} o File options + * @return {JSZip|Object|Array} this JSZip object (when adding a file), + * a file (when searching by string) or an array of files (when searching by regex). + */ + file: function(name, data, o) { + if (arguments.length === 1) { + if (isRegExp(name)) { + var regexp = name; + return this.filter(function(relativePath, file) { + return !file.dir && regexp.test(relativePath); + }); + } + else { // text + var obj = this.files[this.root + name]; + if (obj && !obj.dir) { + return obj; + } else { + return null; + } + } + } + else { // more than one argument : we have data ! + name = this.root + name; + fileAdd.call(this, name, data, o); + } + return this; + }, + + /** + * Add a directory to the zip file, or search. + * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. + * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. + */ + folder: function(arg) { + if (!arg) { + return this; + } + + if (isRegExp(arg)) { + return this.filter(function(relativePath, file) { + return file.dir && arg.test(relativePath); + }); + } + + // else, name is a new folder + var name = this.root + arg; + var newFolder = folderAdd.call(this, name); + + // Allow chaining by returning a new object with this folder as the root + var ret = this.clone(); + ret.root = newFolder.name; + return ret; + }, + + /** + * Delete a file, or a directory and all sub-files, from the zip + * @param {string} name the name of the file to delete + * @return {JSZip} this JSZip object + */ + remove: function(name) { + name = this.root + name; + var file = this.files[name]; + if (!file) { + // Look for any folders + if (name.slice(-1) !== "/") { + name += "/"; + } + file = this.files[name]; + } + + if (file && !file.dir) { + // file + delete this.files[name]; + } else { + // maybe a folder, delete recursively + var kids = this.filter(function(relativePath, file) { + return file.name.slice(0, name.length) === name; + }); + for (var i = 0; i < kids.length; i++) { + delete this.files[kids[i].name]; + } + } + + return this; + }, + + /** + * Generate the complete zip file + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file + */ + generate: function(options) { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + /** + * Generate the complete zip file as an internal stream. + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {StreamHelper} the streamed zip file. + */ + generateInternalStream: function(options) { + var worker, opts = {}; + try { + opts = utils.extend(options || {}, { + streamFiles: false, + compression: "STORE", + compressionOptions : null, + type: "", + platform: "DOS", + comment: null, + mimeType: 'application/zip', + encodeFileName: utf8.utf8encode + }); + + opts.type = opts.type.toLowerCase(); + opts.compression = opts.compression.toUpperCase(); + + // "binarystring" is prefered but the internals use "string". + if(opts.type === "binarystring") { + opts.type = "string"; + } + + if (!opts.type) { + throw new Error("No output type specified."); + } + + utils.checkSupport(opts.type); + + // accept nodejs `process.platform` + if( + opts.platform === 'darwin' || + opts.platform === 'freebsd' || + opts.platform === 'linux' || + opts.platform === 'sunos' + ) { + opts.platform = "UNIX"; + } + if (opts.platform === 'win32') { + opts.platform = "DOS"; + } + + var comment = opts.comment || this.comment || ""; + worker = generate.generateWorker(this, opts, comment); + } catch (e) { + worker = new GenericWorker("error"); + worker.error(e); + } + return new StreamHelper(worker, opts.type || "string", opts.mimeType); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateAsync: function(options, onUpdate) { + return this.generateInternalStream(options).accumulate(onUpdate); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateNodeStream: function(options, onUpdate) { + options = options || {}; + if (!options.type) { + options.type = "nodebuffer"; + } + return this.generateInternalStream(options).toNodejsStream(onUpdate); + } +}; +module.exports = out; + +},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(require,module,exports){ +/* + * This file is used by module bundlers (browserify/webpack/etc) when + * including a stream implementation. We use "readable-stream" to get a + * consistent behavior between nodejs versions but bundlers often have a shim + * for "stream". Using this shim greatly improve the compatibility and greatly + * reduce the final size of the bundle (only one stream implementation, not + * two). + */ +module.exports = require("stream"); + +},{"stream":undefined}],17:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function ArrayReader(data) { + DataReader.call(this, data); + for(var i = 0; i < this.data.length; i++) { + data[i] = data[i] & 0xFF; + } +} +utils.inherits(ArrayReader, DataReader); +/** + * @see DataReader.byteAt + */ +ArrayReader.prototype.byteAt = function(i) { + return this.data[this.zero + i]; +}; +/** + * @see DataReader.lastIndexOfSignature + */ +ArrayReader.prototype.lastIndexOfSignature = function(sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3); + for (var i = this.length - 4; i >= 0; --i) { + if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { + return i - this.zero; + } + } + + return -1; +}; +/** + * @see DataReader.readAndCheckSignature + */ +ArrayReader.prototype.readAndCheckSignature = function (sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3), + data = this.readData(4); + return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3]; +}; +/** + * @see DataReader.readData + */ +ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + return []; + } + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = ArrayReader; + +},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){ +'use strict'; +var utils = require('../utils'); + +function DataReader(data) { + this.data = data; // type : see implementation + this.length = data.length; + this.index = 0; + this.zero = 0; +} +DataReader.prototype = { + /** + * Check that the offset will not go too far. + * @param {string} offset the additional offset to check. + * @throws {Error} an Error if the offset is out of bounds. + */ + checkOffset: function(offset) { + this.checkIndex(this.index + offset); + }, + /** + * Check that the specified index will not be too far. + * @param {string} newIndex the index to check. + * @throws {Error} an Error if the index is out of bounds. + */ + checkIndex: function(newIndex) { + if (this.length < this.zero + newIndex || newIndex < 0) { + throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); + } + }, + /** + * Change the index. + * @param {number} newIndex The new index. + * @throws {Error} if the new index is out of the data. + */ + setIndex: function(newIndex) { + this.checkIndex(newIndex); + this.index = newIndex; + }, + /** + * Skip the next n bytes. + * @param {number} n the number of bytes to skip. + * @throws {Error} if the new index is out of the data. + */ + skip: function(n) { + this.setIndex(this.index + n); + }, + /** + * Get the byte at the specified index. + * @param {number} i the index to use. + * @return {number} a byte. + */ + byteAt: function(i) { + // see implementations + }, + /** + * Get the next number with a given byte size. + * @param {number} size the number of bytes to read. + * @return {number} the corresponding number. + */ + readInt: function(size) { + var result = 0, + i; + this.checkOffset(size); + for (i = this.index + size - 1; i >= this.index; i--) { + result = (result << 8) + this.byteAt(i); + } + this.index += size; + return result; + }, + /** + * Get the next string with a given byte size. + * @param {number} size the number of bytes to read. + * @return {string} the corresponding string. + */ + readString: function(size) { + return utils.transformTo("string", this.readData(size)); + }, + /** + * Get raw data without conversion, bytes. + * @param {number} size the number of bytes to read. + * @return {Object} the raw data, implementation specific. + */ + readData: function(size) { + // see implementations + }, + /** + * Find the last occurence of a zip signature (4 bytes). + * @param {string} sig the signature to find. + * @return {number} the index of the last occurence, -1 if not found. + */ + lastIndexOfSignature: function(sig) { + // see implementations + }, + /** + * Read the signature (4 bytes) at the current position and compare it with sig. + * @param {string} sig the expected signature + * @return {boolean} true if the signature matches, false otherwise. + */ + readAndCheckSignature: function(sig) { + // see implementations + }, + /** + * Get the next date. + * @return {Date} the date. + */ + readDate: function() { + var dostime = this.readInt(4); + return new Date(Date.UTC( + ((dostime >> 25) & 0x7f) + 1980, // year + ((dostime >> 21) & 0x0f) - 1, // month + (dostime >> 16) & 0x1f, // day + (dostime >> 11) & 0x1f, // hour + (dostime >> 5) & 0x3f, // minute + (dostime & 0x1f) << 1)); // second + } +}; +module.exports = DataReader; + +},{"../utils":32}],19:[function(require,module,exports){ +'use strict'; +var Uint8ArrayReader = require('./Uint8ArrayReader'); +var utils = require('../utils'); + +function NodeBufferReader(data) { + Uint8ArrayReader.call(this, data); +} +utils.inherits(NodeBufferReader, Uint8ArrayReader); + +/** + * @see DataReader.readData + */ +NodeBufferReader.prototype.readData = function(size) { + this.checkOffset(size); + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = NodeBufferReader; + +},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function StringReader(data) { + DataReader.call(this, data); +} +utils.inherits(StringReader, DataReader); +/** + * @see DataReader.byteAt + */ +StringReader.prototype.byteAt = function(i) { + return this.data.charCodeAt(this.zero + i); +}; +/** + * @see DataReader.lastIndexOfSignature + */ +StringReader.prototype.lastIndexOfSignature = function(sig) { + return this.data.lastIndexOf(sig) - this.zero; +}; +/** + * @see DataReader.readAndCheckSignature + */ +StringReader.prototype.readAndCheckSignature = function (sig) { + var data = this.readData(4); + return sig === data; +}; +/** + * @see DataReader.readData + */ +StringReader.prototype.readData = function(size) { + this.checkOffset(size); + // this will work because the constructor applied the "& 0xff" mask. + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = StringReader; + +},{"../utils":32,"./DataReader":18}],21:[function(require,module,exports){ +'use strict'; +var ArrayReader = require('./ArrayReader'); +var utils = require('../utils'); + +function Uint8ArrayReader(data) { + ArrayReader.call(this, data); +} +utils.inherits(Uint8ArrayReader, ArrayReader); +/** + * @see DataReader.readData + */ +Uint8ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. + return new Uint8Array(0); + } + var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = Uint8ArrayReader; + +},{"../utils":32,"./ArrayReader":17}],22:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var support = require('../support'); +var ArrayReader = require('./ArrayReader'); +var StringReader = require('./StringReader'); +var NodeBufferReader = require('./NodeBufferReader'); +var Uint8ArrayReader = require('./Uint8ArrayReader'); + +/** + * Create a reader adapted to the data. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read. + * @return {DataReader} the data reader. + */ +module.exports = function (data) { + var type = utils.getTypeOf(data); + utils.checkSupport(type); + if (type === "string" && !support.uint8array) { + return new StringReader(data); + } + if (type === "nodebuffer") { + return new NodeBufferReader(data); + } + if (support.uint8array) { + return new Uint8ArrayReader(utils.transformTo("uint8array", data)); + } + return new ArrayReader(utils.transformTo("array", data)); +}; + +},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(require,module,exports){ +'use strict'; +exports.LOCAL_FILE_HEADER = "PK\x03\x04"; +exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; +exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; +exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; +exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; +exports.DATA_DESCRIPTOR = "PK\x07\x08"; + +},{}],24:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var utils = require('../utils'); + +/** + * A worker which convert chunks to a specified type. + * @constructor + * @param {String} destType the destination type. + */ +function ConvertWorker(destType) { + GenericWorker.call(this, "ConvertWorker to " + destType); + this.destType = destType; +} +utils.inherits(ConvertWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +ConvertWorker.prototype.processChunk = function (chunk) { + this.push({ + data : utils.transformTo(this.destType, chunk.data), + meta : chunk.meta + }); +}; +module.exports = ConvertWorker; + +},{"../utils":32,"./GenericWorker":28}],25:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var crc32 = require('../crc32'); +var utils = require('../utils'); + +/** + * A worker which calculate the crc32 of the data flowing through. + * @constructor + */ +function Crc32Probe() { + GenericWorker.call(this, "Crc32Probe"); + this.withStreamInfo("crc32", 0); +} +utils.inherits(Crc32Probe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Crc32Probe.prototype.processChunk = function (chunk) { + this.streamInfo.crc32 = crc32(chunk.data, this.streamInfo.crc32 || 0); + this.push(chunk); +}; +module.exports = Crc32Probe; + +},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +/** + * A worker which calculate the total length of the data flowing through. + * @constructor + * @param {String} propName the name used to expose the length + */ +function DataLengthProbe(propName) { + GenericWorker.call(this, "DataLengthProbe for " + propName); + this.propName = propName; + this.withStreamInfo(propName, 0); +} +utils.inherits(DataLengthProbe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +DataLengthProbe.prototype.processChunk = function (chunk) { + if(chunk) { + var length = this.streamInfo[this.propName] || 0; + this.streamInfo[this.propName] = length + chunk.data.length; + } + GenericWorker.prototype.processChunk.call(this, chunk); +}; +module.exports = DataLengthProbe; + + +},{"../utils":32,"./GenericWorker":28}],27:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +// the size of the generated chunks +// TODO expose this as a public variable +var DEFAULT_BLOCK_SIZE = 16 * 1024; + +/** + * A worker that reads a content and emits chunks. + * @constructor + * @param {Promise} dataP the promise of the data to split + */ +function DataWorker(dataP) { + GenericWorker.call(this, "DataWorker"); + var self = this; + this.dataIsReady = false; + this.index = 0; + this.max = 0; + this.data = null; + this.type = ""; + + this._tickScheduled = false; + + dataP.then(function (data) { + self.dataIsReady = true; + self.data = data; + self.max = data && data.length || 0; + self.type = utils.getTypeOf(data); + if(!self.isPaused) { + self._tickAndRepeat(); + } + }, function (e) { + self.error(e); + }); +} + +utils.inherits(DataWorker, GenericWorker); + +/** + * @see GenericWorker.cleanUp + */ +DataWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this.data = null; +}; + +/** + * @see GenericWorker.resume + */ +DataWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this._tickScheduled && this.dataIsReady) { + this._tickScheduled = true; + utils.delay(this._tickAndRepeat, [], this); + } + return true; +}; + +/** + * Trigger a tick a schedule an other call to this function. + */ +DataWorker.prototype._tickAndRepeat = function() { + this._tickScheduled = false; + if(this.isPaused || this.isFinished) { + return; + } + this._tick(); + if(!this.isFinished) { + utils.delay(this._tickAndRepeat, [], this); + this._tickScheduled = true; + } +}; + +/** + * Read and push a chunk. + */ +DataWorker.prototype._tick = function() { + + if(this.isPaused || this.isFinished) { + return false; + } + + var size = DEFAULT_BLOCK_SIZE; + var data = null, nextIndex = Math.min(this.max, this.index + size); + if (this.index >= this.max) { + // EOF + return this.end(); + } else { + switch(this.type) { + case "string": + data = this.data.substring(this.index, nextIndex); + break; + case "uint8array": + data = this.data.subarray(this.index, nextIndex); + break; + case "array": + case "nodebuffer": + data = this.data.slice(this.index, nextIndex); + break; + } + this.index = nextIndex; + return this.push({ + data : data, + meta : { + percent : this.max ? this.index / this.max * 100 : 0 + } + }); + } +}; + +module.exports = DataWorker; + +},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){ +'use strict'; + +/** + * A worker that does nothing but passing chunks to the next one. This is like + * a nodejs stream but with some differences. On the good side : + * - it works on IE 6-9 without any issue / polyfill + * - it weights less than the full dependencies bundled with browserify + * - it forwards errors (no need to declare an error handler EVERYWHERE) + * + * A chunk is an object with 2 attributes : `meta` and `data`. The former is an + * object containing anything (`percent` for example), see each worker for more + * details. The latter is the real data (String, Uint8Array, etc). + * + * @constructor + * @param {String} name the name of the stream (mainly used for debugging purposes) + */ +function GenericWorker(name) { + // the name of the worker + this.name = name || "default"; + // an object containing metadata about the workers chain + this.streamInfo = {}; + // an error which happened when the worker was paused + this.generatedError = null; + // an object containing metadata to be merged by this worker into the general metadata + this.extraStreamInfo = {}; + // true if the stream is paused (and should not do anything), false otherwise + this.isPaused = true; + // true if the stream is finished (and should not do anything), false otherwise + this.isFinished = false; + // true if the stream is locked to prevent further structure updates (pipe), false otherwise + this.isLocked = false; + // the event listeners + this._listeners = { + 'data':[], + 'end':[], + 'error':[] + }; + // the previous worker, if any + this.previous = null; +} + +GenericWorker.prototype = { + /** + * Push a chunk to the next workers. + * @param {Object} chunk the chunk to push + */ + push : function (chunk) { + this.emit("data", chunk); + }, + /** + * End the stream. + * @return {Boolean} true if this call ended the worker, false otherwise. + */ + end : function () { + if (this.isFinished) { + return false; + } + + this.flush(); + try { + this.emit("end"); + this.cleanUp(); + this.isFinished = true; + } catch (e) { + this.emit("error", e); + } + return true; + }, + /** + * End the stream with an error. + * @param {Error} e the error which caused the premature end. + * @return {Boolean} true if this call ended the worker with an error, false otherwise. + */ + error : function (e) { + if (this.isFinished) { + return false; + } + + if(this.isPaused) { + this.generatedError = e; + } else { + this.isFinished = true; + + this.emit("error", e); + + // in the workers chain exploded in the middle of the chain, + // the error event will go downward but we also need to notify + // workers upward that there has been an error. + if(this.previous) { + this.previous.error(e); + } + + this.cleanUp(); + } + return true; + }, + /** + * Add a callback on an event. + * @param {String} name the name of the event (data, end, error) + * @param {Function} listener the function to call when the event is triggered + * @return {GenericWorker} the current object for chainability + */ + on : function (name, listener) { + this._listeners[name].push(listener); + return this; + }, + /** + * Clean any references when a worker is ending. + */ + cleanUp : function () { + this.streamInfo = this.generatedError = this.extraStreamInfo = null; + this._listeners = []; + }, + /** + * Trigger an event. This will call registered callback with the provided arg. + * @param {String} name the name of the event (data, end, error) + * @param {Object} arg the argument to call the callback with. + */ + emit : function (name, arg) { + if (this._listeners[name]) { + for(var i = 0; i < this._listeners[name].length; i++) { + this._listeners[name][i].call(this, arg); + } + } + }, + /** + * Chain a worker with an other. + * @param {Worker} next the worker receiving events from the current one. + * @return {worker} the next worker for chainability + */ + pipe : function (next) { + return next.registerPrevious(this); + }, + /** + * Same as `pipe` in the other direction. + * Using an API with `pipe(next)` is very easy. + * Implementing the API with the point of view of the next one registering + * a source is easier, see the ZipFileWorker. + * @param {Worker} previous the previous worker, sending events to this one + * @return {Worker} the current worker for chainability + */ + registerPrevious : function (previous) { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + + // sharing the streamInfo... + this.streamInfo = previous.streamInfo; + // ... and adding our own bits + this.mergeStreamInfo(); + this.previous = previous; + var self = this; + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.end(); + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; + }, + /** + * Pause the stream so it doesn't send events anymore. + * @return {Boolean} true if this call paused the worker, false otherwise. + */ + pause : function () { + if(this.isPaused || this.isFinished) { + return false; + } + this.isPaused = true; + + if(this.previous) { + this.previous.pause(); + } + return true; + }, + /** + * Resume a paused stream. + * @return {Boolean} true if this call resumed the worker, false otherwise. + */ + resume : function () { + if(!this.isPaused || this.isFinished) { + return false; + } + this.isPaused = false; + + // if true, the worker tried to resume but failed + var withError = false; + if(this.generatedError) { + this.error(this.generatedError); + withError = true; + } + if(this.previous) { + this.previous.resume(); + } + + return !withError; + }, + /** + * Flush any remaining bytes as the stream is ending. + */ + flush : function () {}, + /** + * Process a chunk. This is usually the method overridden. + * @param {Object} chunk the chunk to process. + */ + processChunk : function(chunk) { + this.push(chunk); + }, + /** + * Add a key/value to be added in the workers chain streamInfo once activated. + * @param {String} key the key to use + * @param {Object} value the associated value + * @return {Worker} the current worker for chainability + */ + withStreamInfo : function (key, value) { + this.extraStreamInfo[key] = value; + this.mergeStreamInfo(); + return this; + }, + /** + * Merge this worker's streamInfo into the chain's streamInfo. + */ + mergeStreamInfo : function () { + for(var key in this.extraStreamInfo) { + if (!this.extraStreamInfo.hasOwnProperty(key)) { + continue; + } + this.streamInfo[key] = this.extraStreamInfo[key]; + } + }, + + /** + * Lock the stream to prevent further updates on the workers chain. + * After calling this method, all calls to pipe will fail. + */ + lock: function () { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + this.isLocked = true; + if (this.previous) { + this.previous.lock(); + } + }, + + /** + * + * Pretty print the workers chain. + */ + toString : function () { + var me = "Worker " + this.name; + if (this.previous) { + return this.previous + " -> " + me; + } else { + return me; + } + } +}; + +module.exports = GenericWorker; + +},{}],29:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var ConvertWorker = require('./ConvertWorker'); +var GenericWorker = require('./GenericWorker'); +var base64 = require('../base64'); +var support = require("../support"); +var external = require("../external"); + +var NodejsStreamOutputAdapter = null; +if (support.nodestream) { + try { + NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter'); + } catch(e) {} +} + +/** + * Apply the final transformation of the data. If the user wants a Blob for + * example, it's easier to work with an U8intArray and finally do the + * ArrayBuffer/Blob conversion. + * @param {String} type the name of the final type + * @param {String|Uint8Array|Buffer} content the content to transform + * @param {String} mimeType the mime type of the content, if applicable. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. + */ +function transformZipOutput(type, content, mimeType) { + switch(type) { + case "blob" : + return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); + case "base64" : + return base64.encode(content); + default : + return utils.transformTo(type, content); + } +} + +/** + * Concatenate an array of data of the given type. + * @param {String} type the type of the data in the given array. + * @param {Array} dataArray the array containing the data chunks to concatenate + * @return {String|Uint8Array|Buffer} the concatenated data + * @throws Error if the asked type is unsupported + */ +function concat (type, dataArray) { + var i, index = 0, res = null, totalLength = 0; + for(i = 0; i < dataArray.length; i++) { + totalLength += dataArray[i].length; + } + switch(type) { + case "string": + return dataArray.join(""); + case "array": + return Array.prototype.concat.apply([], dataArray); + case "uint8array": + res = new Uint8Array(totalLength); + for(i = 0; i < dataArray.length; i++) { + res.set(dataArray[i], index); + index += dataArray[i].length; + } + return res; + case "nodebuffer": + return Buffer.concat(dataArray); + default: + throw new Error("concat : unsupported type '" + type + "'"); + } +} + +/** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {StreamHelper} helper the helper to use. + * @param {Function} updateCallback a callback called on each update. Called + * with one arg : + * - the metadata linked to the update received. + * @return Promise the promise for the accumulation. + */ +function accumulate(helper, updateCallback) { + return new external.Promise(function (resolve, reject){ + var dataArray = []; + var chunkType = helper._internalType, + resultType = helper._outputType, + mimeType = helper._mimeType; + helper + .on('data', function (data, meta) { + dataArray.push(data); + if(updateCallback) { + updateCallback(meta); + } + }) + .on('error', function(err) { + dataArray = []; + reject(err); + }) + .on('end', function (){ + try { + var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); + resolve(result); + } catch (e) { + reject(e); + } + dataArray = []; + }) + .resume(); + }); +} + +/** + * An helper to easily use workers outside of JSZip. + * @constructor + * @param {Worker} worker the worker to wrap + * @param {String} outputType the type of data expected by the use + * @param {String} mimeType the mime type of the content, if applicable. + */ +function StreamHelper(worker, outputType, mimeType) { + var internalType = outputType; + switch(outputType) { + case "blob": + case "arraybuffer": + internalType = "uint8array"; + break; + case "base64": + internalType = "string"; + break; + } + + try { + // the type used internally + this._internalType = internalType; + // the type used to output results + this._outputType = outputType; + // the mime type + this._mimeType = mimeType; + utils.checkSupport(internalType); + this._worker = worker.pipe(new ConvertWorker(internalType)); + // the last workers can be rewired without issues but we need to + // prevent any updates on previous workers. + worker.lock(); + } catch(e) { + this._worker = new GenericWorker("error"); + this._worker.error(e); + } +} + +StreamHelper.prototype = { + /** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {Function} updateCb the update callback. + * @return Promise the promise for the accumulation. + */ + accumulate : function (updateCb) { + return accumulate(this, updateCb); + }, + /** + * Add a listener on an event triggered on a stream. + * @param {String} evt the name of the event + * @param {Function} fn the listener + * @return {StreamHelper} the current helper. + */ + on : function (evt, fn) { + var self = this; + + if(evt === "data") { + this._worker.on(evt, function (chunk) { + fn.call(self, chunk.data, chunk.meta); + }); + } else { + this._worker.on(evt, function () { + utils.delay(fn, arguments, self); + }); + } + return this; + }, + /** + * Resume the flow of chunks. + * @return {StreamHelper} the current helper. + */ + resume : function () { + utils.delay(this._worker.resume, [], this._worker); + return this; + }, + /** + * Pause the flow of chunks. + * @return {StreamHelper} the current helper. + */ + pause : function () { + this._worker.pause(); + return this; + }, + /** + * Return a nodejs stream for this helper. + * @param {Function} updateCb the update callback. + * @return {NodejsStreamOutputAdapter} the nodejs stream. + */ + toNodejsStream : function (updateCb) { + utils.checkSupport("nodestream"); + if (this._outputType !== "nodebuffer") { + // an object stream containing blob/arraybuffer/uint8array/string + // is strange and I don't know if it would be useful. + // I you find this comment and have a good usecase, please open a + // bug report ! + throw new Error(this._outputType + " is not supported by this method"); + } + + return new NodejsStreamOutputAdapter(this, { + objectMode : this._outputType !== "nodebuffer" + }, updateCb); + } +}; + + +module.exports = StreamHelper; + +},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(require,module,exports){ +'use strict'; + +exports.base64 = true; +exports.array = true; +exports.string = true; +exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; +exports.nodebuffer = typeof Buffer !== "undefined"; +// contains true if JSZip can read/generate Uint8Array, false otherwise. +exports.uint8array = typeof Uint8Array !== "undefined"; + +if (typeof ArrayBuffer === "undefined") { + exports.blob = false; +} +else { + var buffer = new ArrayBuffer(0); + try { + exports.blob = new Blob([buffer], { + type: "application/zip" + }).size === 0; + } + catch (e) { + try { + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + exports.blob = builder.getBlob('application/zip').size === 0; + } + catch (e) { + exports.blob = false; + } + } +} + +try { + exports.nodestream = !!require('readable-stream').Readable; +} catch(e) { + exports.nodestream = false; +} + +},{"readable-stream":16}],31:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var support = require('./support'); +var nodejsUtils = require('./nodejsUtils'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * The following functions come from pako, from pako/lib/utils/strings + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new Array(256); +for (var i=0; i<256; i++) { + _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); +} +_utf8len[254]=_utf8len[254]=1; // Invalid sequence start + +// convert string to array (typed, when possible) +var string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + if (support.uint8array) { + buf = new Uint8Array(buf_len); + } else { + buf = new Array(buf_len); + } + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +var utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +// convert array to string +var buf2string = function (buf) { + var str, i, out, c, c_len; + var len = buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + // shrinkBuf(utf16buf, out) + if (utf16buf.length !== out) { + if(utf16buf.subarray) { + utf16buf = utf16buf.subarray(0, out); + } else { + utf16buf.length = out; + } + } + + // return String.fromCharCode.apply(null, utf16buf); + return utils.applyFromCharCode(utf16buf); +}; + + +// That's all for the pako functions. + + +/** + * Transform a javascript string into an array (typed if possible) of bytes, + * UTF-8 encoded. + * @param {String} str the string to encode + * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. + */ +exports.utf8encode = function utf8encode(str) { + if (support.nodebuffer) { + return nodejsUtils.newBufferFrom(str, "utf-8"); + } + + return string2buf(str); +}; + + +/** + * Transform a bytes array (or a representation) representing an UTF-8 encoded + * string into a javascript string. + * @param {Array|Uint8Array|Buffer} buf the data de decode + * @return {String} the decoded string. + */ +exports.utf8decode = function utf8decode(buf) { + if (support.nodebuffer) { + return utils.transformTo("nodebuffer", buf).toString("utf-8"); + } + + buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); + + return buf2string(buf); +}; + +/** + * A worker to decode utf8 encoded binary chunks into string chunks. + * @constructor + */ +function Utf8DecodeWorker() { + GenericWorker.call(this, "utf-8 decode"); + // the last bytes if a chunk didn't end with a complete codepoint. + this.leftOver = null; +} +utils.inherits(Utf8DecodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8DecodeWorker.prototype.processChunk = function (chunk) { + + var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data); + + // 1st step, re-use what's left of the previous chunk + if (this.leftOver && this.leftOver.length) { + if(support.uint8array) { + var previousData = data; + data = new Uint8Array(previousData.length + this.leftOver.length); + data.set(this.leftOver, 0); + data.set(previousData, this.leftOver.length); + } else { + data = this.leftOver.concat(data); + } + this.leftOver = null; + } + + var nextBoundary = utf8border(data); + var usableData = data; + if (nextBoundary !== data.length) { + if (support.uint8array) { + usableData = data.subarray(0, nextBoundary); + this.leftOver = data.subarray(nextBoundary, data.length); + } else { + usableData = data.slice(0, nextBoundary); + this.leftOver = data.slice(nextBoundary, data.length); + } + } + + this.push({ + data : exports.utf8decode(usableData), + meta : chunk.meta + }); +}; + +/** + * @see GenericWorker.flush + */ +Utf8DecodeWorker.prototype.flush = function () { + if(this.leftOver && this.leftOver.length) { + this.push({ + data : exports.utf8decode(this.leftOver), + meta : {} + }); + this.leftOver = null; + } +}; +exports.Utf8DecodeWorker = Utf8DecodeWorker; + +/** + * A worker to endcode string chunks into utf8 encoded binary chunks. + * @constructor + */ +function Utf8EncodeWorker() { + GenericWorker.call(this, "utf-8 encode"); +} +utils.inherits(Utf8EncodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8EncodeWorker.prototype.processChunk = function (chunk) { + this.push({ + data : exports.utf8encode(chunk.data), + meta : chunk.meta + }); +}; +exports.Utf8EncodeWorker = Utf8EncodeWorker; + +},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){ +'use strict'; + +var support = require('./support'); +var base64 = require('./base64'); +var nodejsUtils = require('./nodejsUtils'); +var setImmediate = require('core-js/library/fn/set-immediate'); +var external = require("./external"); + + +/** + * Convert a string that pass as a "binary string": it should represent a byte + * array but may have > 255 char codes. Be sure to take only the first byte + * and returns the byte array. + * @param {String} str the string to transform. + * @return {Array|Uint8Array} the string in a binary format. + */ +function string2binary(str) { + var result = null; + if (support.uint8array) { + result = new Uint8Array(str.length); + } else { + result = new Array(str.length); + } + return stringToArrayLike(str, result); +} + +/** + * Create a new blob with the given content and the given type. + * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use + * an Uint8Array because the stock browser of android 4 won't accept it (it + * will be silently converted to a string, "[object Uint8Array]"). + * + * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: + * when a large amount of Array is used to create the Blob, the amount of + * memory consumed is nearly 100 times the original data amount. + * + * @param {String} type the mime type of the blob. + * @return {Blob} the created blob. + */ +exports.newBlob = function(part, type) { + exports.checkSupport("blob"); + + try { + // Blob constructor + return new Blob([part], { + type: type + }); + } + catch (e) { + + try { + // deprecated, browser only, old way + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(part); + return builder.getBlob(type); + } + catch (e) { + + // well, fuck ?! + throw new Error("Bug : can't construct the Blob."); + } + } + + +}; +/** + * The identity function. + * @param {Object} input the input. + * @return {Object} the same input. + */ +function identity(input) { + return input; +} + +/** + * Fill in an array with a string. + * @param {String} str the string to use. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. + */ +function stringToArrayLike(str, array) { + for (var i = 0; i < str.length; ++i) { + array[i] = str.charCodeAt(i) & 0xFF; + } + return array; +} + +/** + * An helper for the function arrayLikeToString. + * This contains static informations and functions that + * can be optimized by the browser JIT compiler. + */ +var arrayToStringHelper = { + /** + * Transform an array of int into a string, chunk by chunk. + * See the performances notes on arrayLikeToString. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @param {String} type the type of the array. + * @param {Integer} chunk the chunk size. + * @return {String} the resulting string. + * @throws Error if the chunk is too big for the stack. + */ + stringifyByChunk: function(array, type, chunk) { + var result = [], k = 0, len = array.length; + // shortcut + if (len <= chunk) { + return String.fromCharCode.apply(null, array); + } + while (k < len) { + if (type === "array" || type === "nodebuffer") { + result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); + } + else { + result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); + } + k += chunk; + } + return result.join(""); + }, + /** + * Call String.fromCharCode on every item in the array. + * This is the naive implementation, which generate A LOT of intermediate string. + * This should be used when everything else fail. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ + stringifyByChar: function(array){ + var resultStr = ""; + for(var i = 0; i < array.length; i++) { + resultStr += String.fromCharCode(array[i]); + } + return resultStr; + }, + applyCanBeUsed : { + /** + * true if the browser accepts to use String.fromCharCode on Uint8Array + */ + uint8array : (function () { + try { + return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; + } catch (e) { + return false; + } + })(), + /** + * true if the browser accepts to use String.fromCharCode on nodejs Buffer. + */ + nodebuffer : (function () { + try { + return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; + } catch (e) { + return false; + } + })() + } +}; + +/** + * Transform an array-like object to a string. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ +function arrayLikeToString(array) { + // Performances notes : + // -------------------- + // String.fromCharCode.apply(null, array) is the fastest, see + // see http://jsperf.com/converting-a-uint8array-to-a-string/2 + // but the stack is limited (and we can get huge arrays !). + // + // result += String.fromCharCode(array[i]); generate too many strings ! + // + // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 + // TODO : we now have workers that split the work. Do we still need that ? + var chunk = 65536, + type = exports.getTypeOf(array), + canUseApply = true; + if (type === "uint8array") { + canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; + } else if (type === "nodebuffer") { + canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; + } + + if (canUseApply) { + while (chunk > 1) { + try { + return arrayToStringHelper.stringifyByChunk(array, type, chunk); + } catch (e) { + chunk = Math.floor(chunk / 2); + } + } + } + + // no apply or chunk error : slow and painful algorithm + // default browser on android 4.* + return arrayToStringHelper.stringifyByChar(array); +} + +exports.applyFromCharCode = arrayLikeToString; + + +/** + * Copy the data from an array-like to an other array-like. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. + */ +function arrayLikeToArrayLike(arrayFrom, arrayTo) { + for (var i = 0; i < arrayFrom.length; i++) { + arrayTo[i] = arrayFrom[i]; + } + return arrayTo; +} + +// a matrix containing functions to transform everything into everything. +var transform = {}; + +// string to ? +transform["string"] = { + "string": identity, + "array": function(input) { + return stringToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["string"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return stringToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": function(input) { + return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); + } +}; + +// array to ? +transform["array"] = { + "string": arrayLikeToString, + "array": identity, + "arraybuffer": function(input) { + return (new Uint8Array(input)).buffer; + }, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// arraybuffer to ? +transform["arraybuffer"] = { + "string": function(input) { + return arrayLikeToString(new Uint8Array(input)); + }, + "array": function(input) { + return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); + }, + "arraybuffer": identity, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(new Uint8Array(input)); + } +}; + +// uint8array to ? +transform["uint8array"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return input.buffer; + }, + "uint8array": identity, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// nodebuffer to ? +transform["nodebuffer"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["nodebuffer"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return arrayLikeToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": identity +}; + +/** + * Transform an input into any type. + * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. + * If no output type is specified, the unmodified input will be returned. + * @param {String} outputType the output type. + * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. + * @throws {Error} an Error if the browser doesn't support the requested output type. + */ +exports.transformTo = function(outputType, input) { + if (!input) { + // undefined, null, etc + // an empty string won't harm. + input = ""; + } + if (!outputType) { + return input; + } + exports.checkSupport(outputType); + var inputType = exports.getTypeOf(input); + var result = transform[inputType][outputType](input); + return result; +}; + +/** + * Return the type of the input. + * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. + * @param {Object} input the input to identify. + * @return {String} the (lowercase) type of the input. + */ +exports.getTypeOf = function(input) { + if (typeof input === "string") { + return "string"; + } + if (Object.prototype.toString.call(input) === "[object Array]") { + return "array"; + } + if (support.nodebuffer && nodejsUtils.isBuffer(input)) { + return "nodebuffer"; + } + if (support.uint8array && input instanceof Uint8Array) { + return "uint8array"; + } + if (support.arraybuffer && input instanceof ArrayBuffer) { + return "arraybuffer"; + } +}; + +/** + * Throw an exception if the type is not supported. + * @param {String} type the type to check. + * @throws {Error} an Error if the browser doesn't support the requested type. + */ +exports.checkSupport = function(type) { + var supported = support[type.toLowerCase()]; + if (!supported) { + throw new Error(type + " is not supported by this platform"); + } +}; + +exports.MAX_VALUE_16BITS = 65535; +exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 + +/** + * Prettify a string read as binary. + * @param {string} str the string to prettify. + * @return {string} a pretty string. + */ +exports.pretty = function(str) { + var res = '', + code, i; + for (i = 0; i < (str || "").length; i++) { + code = str.charCodeAt(i); + res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); + } + return res; +}; + +/** + * Defer the call of a function. + * @param {Function} callback the function to call asynchronously. + * @param {Array} args the arguments to give to the callback. + */ +exports.delay = function(callback, args, self) { + setImmediate(function () { + callback.apply(self || null, args || []); + }); +}; + +/** + * Extends a prototype with an other, without calling a constructor with + * side effects. Inspired by nodejs' `utils.inherits` + * @param {Function} ctor the constructor to augment + * @param {Function} superCtor the parent constructor to use + */ +exports.inherits = function (ctor, superCtor) { + var Obj = function() {}; + Obj.prototype = superCtor.prototype; + ctor.prototype = new Obj(); +}; + +/** + * Merge the objects passed as parameters into a new one. + * @private + * @param {...Object} var_args All objects to merge. + * @return {Object} a new object with the data of the others. + */ +exports.extend = function() { + var result = {}, i, attr; + for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers + for (attr in arguments[i]) { + if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { + result[attr] = arguments[i][attr]; + } + } + } + return result; +}; + +/** + * Transform arbitrary content into a Promise. + * @param {String} name a name for the content being processed. + * @param {Object} inputData the content to process. + * @param {Boolean} isBinary true if the content is not an unicode string + * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. + * @param {Boolean} isBase64 true if the string content is encoded with base64. + * @return {Promise} a promise in a format usable by JSZip. + */ +exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { + + // if inputData is already a promise, this flatten it. + var promise = external.Promise.resolve(inputData).then(function(data) { + + + var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); + + if (isBlob && typeof FileReader !== "undefined") { + return new external.Promise(function (resolve, reject) { + var reader = new FileReader(); + + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e.target.error); + }; + reader.readAsArrayBuffer(data); + }); + } else { + return data; + } + }); + + return promise.then(function(data) { + var dataType = exports.getTypeOf(data); + + if (!dataType) { + return external.Promise.reject( + new Error("Can't read the data of '" + name + "'. Is it " + + "in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") + ); + } + // special case : it's way easier to work with Uint8Array than with ArrayBuffer + if (dataType === "arraybuffer") { + data = exports.transformTo("uint8array", data); + } else if (dataType === "string") { + if (isBase64) { + data = base64.decode(data); + } + else if (isBinary) { + // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask + if (isOptimizedBinaryString !== true) { + // this is a string, not in a base64 format. + // Be sure that this is a correct "binary string" + data = string2binary(data); + } + } + } + return data; + }); +}; + +},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"core-js/library/fn/set-immediate":36}],33:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var sig = require('./signature'); +var ZipEntry = require('./zipEntry'); +var utf8 = require('./utf8'); +var support = require('./support'); +// class ZipEntries {{{ +/** + * All the entries in the zip file. + * @constructor + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntries(loadOptions) { + this.files = []; + this.loadOptions = loadOptions; +} +ZipEntries.prototype = { + /** + * Check that the reader is on the specified signature. + * @param {string} expectedSignature the expected signature. + * @throws {Error} if it is an other signature. + */ + checkSignature: function(expectedSignature) { + if (!this.reader.readAndCheckSignature(expectedSignature)) { + this.reader.index -= 4; + var signature = this.reader.readString(4); + throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); + } + }, + /** + * Check if the given signature is at the given index. + * @param {number} askedIndex the index to check. + * @param {string} expectedSignature the signature to expect. + * @return {boolean} true if the signature is here, false otherwise. + */ + isSignature: function(askedIndex, expectedSignature) { + var currentIndex = this.reader.index; + this.reader.setIndex(askedIndex); + var signature = this.reader.readString(4); + var result = signature === expectedSignature; + this.reader.setIndex(currentIndex); + return result; + }, + /** + * Read the end of the central directory. + */ + readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2); + this.diskWithCentralDirStart = this.reader.readInt(2); + this.centralDirRecordsOnThisDisk = this.reader.readInt(2); + this.centralDirRecords = this.reader.readInt(2); + this.centralDirSize = this.reader.readInt(4); + this.centralDirOffset = this.reader.readInt(4); + + this.zipCommentLength = this.reader.readInt(2); + // warning : the encoding depends of the system locale + // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. + // On a windows machine, this field is encoded with the localized windows code page. + var zipComment = this.reader.readData(this.zipCommentLength); + var decodeParamType = support.uint8array ? "uint8array" : "array"; + // To get consistent behavior with the generation part, we will assume that + // this is utf8 encoded unless specified otherwise. + var decodeContent = utils.transformTo(decodeParamType, zipComment); + this.zipComment = this.loadOptions.decodeFileName(decodeContent); + }, + /** + * Read the end of the Zip 64 central directory. + * Not merged with the method readEndOfCentral : + * The end of central can coexist with its Zip64 brother, + * I don't want to read the wrong number of bytes ! + */ + readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8); + this.reader.skip(4); + // this.versionMadeBy = this.reader.readString(2); + // this.versionNeeded = this.reader.readInt(2); + this.diskNumber = this.reader.readInt(4); + this.diskWithCentralDirStart = this.reader.readInt(4); + this.centralDirRecordsOnThisDisk = this.reader.readInt(8); + this.centralDirRecords = this.reader.readInt(8); + this.centralDirSize = this.reader.readInt(8); + this.centralDirOffset = this.reader.readInt(8); + + this.zip64ExtensibleData = {}; + var extraDataSize = this.zip64EndOfCentralSize - 44, + index = 0, + extraFieldId, + extraFieldLength, + extraFieldValue; + while (index < extraDataSize) { + extraFieldId = this.reader.readInt(2); + extraFieldLength = this.reader.readInt(4); + extraFieldValue = this.reader.readData(extraFieldLength); + this.zip64ExtensibleData[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Read the end of the Zip 64 central directory locator. + */ + readBlockZip64EndOfCentralLocator: function() { + this.diskWithZip64CentralDirStart = this.reader.readInt(4); + this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); + this.disksCount = this.reader.readInt(4); + if (this.disksCount > 1) { + throw new Error("Multi-volumes zip are not supported"); + } + }, + /** + * Read the local files, based on the offset read in the central part. + */ + readLocalFiles: function() { + var i, file; + for (i = 0; i < this.files.length; i++) { + file = this.files[i]; + this.reader.setIndex(file.localHeaderOffset); + this.checkSignature(sig.LOCAL_FILE_HEADER); + file.readLocalPart(this.reader); + file.handleUTF8(); + file.processAttributes(); + } + }, + /** + * Read the central directory. + */ + readCentralDir: function() { + var file; + + this.reader.setIndex(this.centralDirOffset); + while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) { + file = new ZipEntry({ + zip64: this.zip64 + }, this.loadOptions); + file.readCentralPart(this.reader); + this.files.push(file); + } + + if (this.centralDirRecords !== this.files.length) { + if (this.centralDirRecords !== 0 && this.files.length === 0) { + // We expected some records but couldn't find ANY. + // This is really suspicious, as if something went wrong. + throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); + } else { + // We found some records but not all. + // Something is wrong but we got something for the user: no error here. + // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length); + } + } + }, + /** + * Read the end of central directory. + */ + readEndOfCentral: function() { + var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); + if (offset < 0) { + // Check if the content is a truncated zip or complete garbage. + // A "LOCAL_FILE_HEADER" is not required at the beginning (auto + // extractible zip for example) but it can give a good hint. + // If an ajax request was used without responseType, we will also + // get unreadable data. + var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER); + + if (isGarbage) { + throw new Error("Can't find end of central directory : is this a zip file ? " + + "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"); + } else { + throw new Error("Corrupted zip: can't find end of central directory"); + } + + } + this.reader.setIndex(offset); + var endOfCentralDirOffset = offset; + this.checkSignature(sig.CENTRAL_DIRECTORY_END); + this.readBlockEndOfCentral(); + + + /* extract from the zip spec : + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + */ + if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { + this.zip64 = true; + + /* + Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from + the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents + all numbers as 64-bit double precision IEEE 754 floating point numbers. + So, we have 53bits for integers and bitwise operations treat everything as 32bits. + see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators + and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 + */ + + // should look for a zip64 EOCD locator + offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + if (offset < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + this.readBlockZip64EndOfCentralLocator(); + + // now the zip64 EOCD record + if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) { + // console.warn("ZIP64 end of central directory not where expected."); + this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + if (this.relativeOffsetEndOfZip64CentralDir < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); + } + } + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + this.readBlockZip64EndOfCentral(); + } + + var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize; + if (this.zip64) { + expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator + expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize; + } + + var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset; + + if (extraBytes > 0) { + // console.warn(extraBytes, "extra bytes at beginning or within zipfile"); + if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) { + // The offsets seem wrong, but we have something at the specified offset. + // So… we keep it. + } else { + // the offset is wrong, update the "zero" of the reader + // this happens if data has been prepended (crx files for example) + this.reader.zero = extraBytes; + } + } else if (extraBytes < 0) { + throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes."); + } + }, + prepareReader: function(data) { + this.reader = readerFor(data); + }, + /** + * Read a zip file and create ZipEntries. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. + */ + load: function(data) { + this.prepareReader(data); + this.readEndOfCentral(); + this.readCentralDir(); + this.readLocalFiles(); + } +}; +// }}} end of ZipEntries +module.exports = ZipEntries; + +},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var CompressedObject = require('./compressedObject'); +var crc32fn = require('./crc32'); +var utf8 = require('./utf8'); +var compressions = require('./compressions'); +var support = require('./support'); + +var MADE_BY_DOS = 0x00; +var MADE_BY_UNIX = 0x03; + +/** + * Find a compression registered in JSZip. + * @param {string} compressionMethod the method magic to find. + * @return {Object|null} the JSZip compression object, null if none found. + */ +var findCompression = function(compressionMethod) { + for (var method in compressions) { + if (!compressions.hasOwnProperty(method)) { + continue; + } + if (compressions[method].magic === compressionMethod) { + return compressions[method]; + } + } + return null; +}; + +// class ZipEntry {{{ +/** + * An entry in the zip file. + * @constructor + * @param {Object} options Options of the current file. + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntry(options, loadOptions) { + this.options = options; + this.loadOptions = loadOptions; +} +ZipEntry.prototype = { + /** + * say if the file is encrypted. + * @return {boolean} true if the file is encrypted, false otherwise. + */ + isEncrypted: function() { + // bit 1 is set + return (this.bitFlag & 0x0001) === 0x0001; + }, + /** + * say if the file has utf-8 filename/comment. + * @return {boolean} true if the filename/comment is in utf-8, false otherwise. + */ + useUTF8: function() { + // bit 11 is set + return (this.bitFlag & 0x0800) === 0x0800; + }, + /** + * Read the local part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readLocalPart: function(reader) { + var compression, localExtraFieldsLength; + + // we already know everything from the central dir ! + // If the central dir data are false, we are doomed. + // On the bright side, the local part is scary : zip64, data descriptors, both, etc. + // The less data we get here, the more reliable this should be. + // Let's skip the whole header and dash to the data ! + reader.skip(22); + // in some zip created on windows, the filename stored in the central dir contains \ instead of /. + // Strangely, the filename here is OK. + // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes + // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... + // Search "unzip mismatching "local" filename continuing with "central" filename version" on + // the internet. + // + // I think I see the logic here : the central directory is used to display + // content and the local directory is used to extract the files. Mixing / and \ + // may be used to display \ to windows users and use / when extracting the files. + // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 + this.fileNameLength = reader.readInt(2); + localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir + // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding. + this.fileName = reader.readData(this.fileNameLength); + reader.skip(localExtraFieldsLength); + + if (this.compressedSize === -1 || this.uncompressedSize === -1) { + throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)"); + } + + compression = findCompression(this.compressionMethod); + if (compression === null) { // no compression found + throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")"); + } + this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize)); + }, + + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readCentralPart: function(reader) { + this.versionMadeBy = reader.readInt(2); + reader.skip(2); + // this.versionNeeded = reader.readInt(2); + this.bitFlag = reader.readInt(2); + this.compressionMethod = reader.readString(2); + this.date = reader.readDate(); + this.crc32 = reader.readInt(4); + this.compressedSize = reader.readInt(4); + this.uncompressedSize = reader.readInt(4); + var fileNameLength = reader.readInt(2); + this.extraFieldsLength = reader.readInt(2); + this.fileCommentLength = reader.readInt(2); + this.diskNumberStart = reader.readInt(2); + this.internalFileAttributes = reader.readInt(2); + this.externalFileAttributes = reader.readInt(4); + this.localHeaderOffset = reader.readInt(4); + + if (this.isEncrypted()) { + throw new Error("Encrypted zip are not supported"); + } + + // will be read in the local part, see the comments there + reader.skip(fileNameLength); + this.readExtraFields(reader); + this.parseZIP64ExtraField(reader); + this.fileComment = reader.readData(this.fileCommentLength); + }, + + /** + * Parse the external file attributes and get the unix/dos permissions. + */ + processAttributes: function () { + this.unixPermissions = null; + this.dosPermissions = null; + var madeBy = this.versionMadeBy >> 8; + + // Check if we have the DOS directory flag set. + // We look for it in the DOS and UNIX permissions + // but some unknown platform could set it as a compatibility flag. + this.dir = this.externalFileAttributes & 0x0010 ? true : false; + + if(madeBy === MADE_BY_DOS) { + // first 6 bits (0 to 5) + this.dosPermissions = this.externalFileAttributes & 0x3F; + } + + if(madeBy === MADE_BY_UNIX) { + this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; + // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); + } + + // fail safe : if the name ends with a / it probably means a folder + if (!this.dir && this.fileNameStr.slice(-1) === '/') { + this.dir = true; + } + }, + + /** + * Parse the ZIP64 extra field and merge the info in the current ZipEntry. + * @param {DataReader} reader the reader to use. + */ + parseZIP64ExtraField: function(reader) { + + if (!this.extraFields[0x0001]) { + return; + } + + // should be something, preparing the extra reader + var extraReader = readerFor(this.extraFields[0x0001].value); + + // I really hope that these 64bits integer can fit in 32 bits integer, because js + // won't let us have more. + if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { + this.uncompressedSize = extraReader.readInt(8); + } + if (this.compressedSize === utils.MAX_VALUE_32BITS) { + this.compressedSize = extraReader.readInt(8); + } + if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { + this.localHeaderOffset = extraReader.readInt(8); + } + if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { + this.diskNumberStart = extraReader.readInt(4); + } + }, + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readExtraFields: function(reader) { + var end = reader.index + this.extraFieldsLength, + extraFieldId, + extraFieldLength, + extraFieldValue; + + if (!this.extraFields) { + this.extraFields = {}; + } + + while (reader.index < end) { + extraFieldId = reader.readInt(2); + extraFieldLength = reader.readInt(2); + extraFieldValue = reader.readData(extraFieldLength); + + this.extraFields[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Apply an UTF8 transformation if needed. + */ + handleUTF8: function() { + var decodeParamType = support.uint8array ? "uint8array" : "array"; + if (this.useUTF8()) { + this.fileNameStr = utf8.utf8decode(this.fileName); + this.fileCommentStr = utf8.utf8decode(this.fileComment); + } else { + var upath = this.findExtraFieldUnicodePath(); + if (upath !== null) { + this.fileNameStr = upath; + } else { + // ASCII text or unsupported code page + var fileNameByteArray = utils.transformTo(decodeParamType, this.fileName); + this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray); + } + + var ucomment = this.findExtraFieldUnicodeComment(); + if (ucomment !== null) { + this.fileCommentStr = ucomment; + } else { + // ASCII text or unsupported code page + var commentByteArray = utils.transformTo(decodeParamType, this.fileComment); + this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray); + } + } + }, + + /** + * Find the unicode path declared in the extra field, if any. + * @return {String} the unicode path, null otherwise. + */ + findExtraFieldUnicodePath: function() { + var upathField = this.extraFields[0x7075]; + if (upathField) { + var extraReader = readerFor(upathField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the filename changed, this field is out of date. + if (crc32fn(this.fileName) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(upathField.length - 5)); + } + return null; + }, + + /** + * Find the unicode comment declared in the extra field, if any. + * @return {String} the unicode comment, null otherwise. + */ + findExtraFieldUnicodeComment: function() { + var ucommentField = this.extraFields[0x6375]; + if (ucommentField) { + var extraReader = readerFor(ucommentField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the comment changed, this field is out of date. + if (crc32fn(this.fileComment) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(ucommentField.length - 5)); + } + return null; + } +}; +module.exports = ZipEntry; + +},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(require,module,exports){ +'use strict'; + +var StreamHelper = require('./stream/StreamHelper'); +var DataWorker = require('./stream/DataWorker'); +var utf8 = require('./utf8'); +var CompressedObject = require('./compressedObject'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * A simple object representing a file in the zip file. + * @constructor + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data + * @param {Object} options the options of the file + */ +var ZipObject = function(name, data, options) { + this.name = name; + this.dir = options.dir; + this.date = options.date; + this.comment = options.comment; + this.unixPermissions = options.unixPermissions; + this.dosPermissions = options.dosPermissions; + + this._data = data; + this._dataBinary = options.binary; + // keep only the compression + this.options = { + compression : options.compression, + compressionOptions : options.compressionOptions + }; +}; + +ZipObject.prototype = { + /** + * Create an internal stream for the content of this object. + * @param {String} type the type of each chunk. + * @return StreamHelper the stream. + */ + internalStream: function (type) { + var result = null, outputType = "string"; + try { + if (!type) { + throw new Error("No output type specified."); + } + outputType = type.toLowerCase(); + var askUnicodeString = outputType === "string" || outputType === "text"; + if (outputType === "binarystring" || outputType === "text") { + outputType = "string"; + } + result = this._decompressWorker(); + + var isUnicodeString = !this._dataBinary; + + if (isUnicodeString && !askUnicodeString) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + if (!isUnicodeString && askUnicodeString) { + result = result.pipe(new utf8.Utf8DecodeWorker()); + } + } catch (e) { + result = new GenericWorker("error"); + result.error(e); + } + + return new StreamHelper(result, outputType, ""); + }, + + /** + * Prepare the content in the asked type. + * @param {String} type the type of the result. + * @param {Function} onUpdate a function to call on each internal update. + * @return Promise the promise of the result. + */ + async: function (type, onUpdate) { + return this.internalStream(type).accumulate(onUpdate); + }, + + /** + * Prepare the content as a nodejs stream. + * @param {String} type the type of each chunk. + * @param {Function} onUpdate a function to call on each internal update. + * @return Stream the stream. + */ + nodeStream: function (type, onUpdate) { + return this.internalStream(type || "nodebuffer").toNodejsStream(onUpdate); + }, + + /** + * Return a worker for the compressed content. + * @private + * @param {Object} compression the compression object to use. + * @param {Object} compressionOptions the options to use when compressing. + * @return Worker the worker. + */ + _compressWorker: function (compression, compressionOptions) { + if ( + this._data instanceof CompressedObject && + this._data.compression.magic === compression.magic + ) { + return this._data.getCompressedWorker(); + } else { + var result = this._decompressWorker(); + if(!this._dataBinary) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + return CompressedObject.createWorkerFrom(result, compression, compressionOptions); + } + }, + /** + * Return a worker for the decompressed content. + * @private + * @return Worker the worker. + */ + _decompressWorker : function () { + if (this._data instanceof CompressedObject) { + return this._data.getContentWorker(); + } else if (this._data instanceof GenericWorker) { + return this._data; + } else { + return new DataWorker(this._data); + } + } +}; + +var removedMethods = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"]; +var removedFn = function () { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); +}; + +for(var i = 0; i < removedMethods.length; i++) { + ZipObject.prototype[removedMethods[i]] = removedFn; +} +module.exports = ZipObject; + +},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(require,module,exports){ +require('../modules/web.immediate'); +module.exports = require('../modules/_core').setImmediate; +},{"../modules/_core":40,"../modules/web.immediate":56}],37:[function(require,module,exports){ +module.exports = function(it){ + if(typeof it != 'function')throw TypeError(it + ' is not a function!'); + return it; +}; +},{}],38:[function(require,module,exports){ +var isObject = require('./_is-object'); +module.exports = function(it){ + if(!isObject(it))throw TypeError(it + ' is not an object!'); + return it; +}; +},{"./_is-object":51}],39:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = function(it){ + return toString.call(it).slice(8, -1); +}; +},{}],40:[function(require,module,exports){ +var core = module.exports = {version: '2.3.0'}; +if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef +},{}],41:[function(require,module,exports){ +// optional / simple context binding +var aFunction = require('./_a-function'); +module.exports = function(fn, that, length){ + aFunction(fn); + if(that === undefined)return fn; + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; +}; +},{"./_a-function":37}],42:[function(require,module,exports){ +// Thank's IE8 for his funny defineProperty +module.exports = !require('./_fails')(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_fails":45}],43:[function(require,module,exports){ +var isObject = require('./_is-object') + , document = require('./_global').document + // in old IE typeof document.createElement is 'object' + , is = isObject(document) && isObject(document.createElement); +module.exports = function(it){ + return is ? document.createElement(it) : {}; +}; +},{"./_global":46,"./_is-object":51}],44:[function(require,module,exports){ +var global = require('./_global') + , core = require('./_core') + , ctx = require('./_ctx') + , hide = require('./_hide') + , PROTOTYPE = 'prototype'; + +var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , IS_WRAP = type & $export.W + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] + , key, own, out; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if(own && key in exports)continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function(C){ + var F = function(a, b, c){ + if(this instanceof C){ + switch(arguments.length){ + case 0: return new C; + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if(IS_PROTO){ + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); + } + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; +},{"./_core":40,"./_ctx":41,"./_global":46,"./_hide":47}],45:[function(require,module,exports){ +module.exports = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } +}; +},{}],46:[function(require,module,exports){ +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); +if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef +},{}],47:[function(require,module,exports){ +var dP = require('./_object-dp') + , createDesc = require('./_property-desc'); +module.exports = require('./_descriptors') ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); +} : function(object, key, value){ + object[key] = value; + return object; +}; +},{"./_descriptors":42,"./_object-dp":52,"./_property-desc":53}],48:[function(require,module,exports){ +module.exports = require('./_global').document && document.documentElement; +},{"./_global":46}],49:[function(require,module,exports){ +module.exports = !require('./_descriptors') && !require('./_fails')(function(){ + return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_descriptors":42,"./_dom-create":43,"./_fails":45}],50:[function(require,module,exports){ +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function(fn, args, that){ + var un = that === undefined; + switch(args.length){ + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; +},{}],51:[function(require,module,exports){ +module.exports = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; +},{}],52:[function(require,module,exports){ +var anObject = require('./_an-object') + , IE8_DOM_DEFINE = require('./_ie8-dom-define') + , toPrimitive = require('./_to-primitive') + , dP = Object.defineProperty; + +exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){ + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if(IE8_DOM_DEFINE)try { + return dP(O, P, Attributes); + } catch(e){ /* empty */ } + if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); + if('value' in Attributes)O[P] = Attributes.value; + return O; +}; +},{"./_an-object":38,"./_descriptors":42,"./_ie8-dom-define":49,"./_to-primitive":55}],53:[function(require,module,exports){ +module.exports = function(bitmap, value){ + return { + enumerable : !(bitmap & 1), + configurable: !(bitmap & 2), + writable : !(bitmap & 4), + value : value + }; +}; +},{}],54:[function(require,module,exports){ +var ctx = require('./_ctx') + , invoke = require('./_invoke') + , html = require('./_html') + , cel = require('./_dom-create') + , global = require('./_global') + , process = global.process + , setTask = global.setImmediate + , clearTask = global.clearImmediate + , MessageChannel = global.MessageChannel + , counter = 0 + , queue = {} + , ONREADYSTATECHANGE = 'onreadystatechange' + , defer, channel, port; +var run = function(){ + var id = +this; + if(queue.hasOwnProperty(id)){ + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function(event){ + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if(!setTask || !clearTask){ + setTask = function setImmediate(fn){ + var args = [], i = 1; + while(arguments.length > i)args.push(arguments[i++]); + queue[++counter] = function(){ + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id){ + delete queue[id]; + }; + // Node.js 0.8- + if(require('./_cof')(process) == 'process'){ + defer = function(id){ + process.nextTick(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if(MessageChannel){ + channel = new MessageChannel; + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ + defer = function(id){ + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if(ONREADYSTATECHANGE in cel('script')){ + defer = function(id){ + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function(id){ + setTimeout(ctx(run, id, 1), 0); + }; + } +} +module.exports = { + set: setTask, + clear: clearTask +}; +},{"./_cof":39,"./_ctx":41,"./_dom-create":43,"./_global":46,"./_html":48,"./_invoke":50}],55:[function(require,module,exports){ +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = require('./_is-object'); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function(it, S){ + if(!isObject(it))return it; + var fn, val; + if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; + if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + throw TypeError("Can't convert object to primitive value"); +}; +},{"./_is-object":51}],56:[function(require,module,exports){ +var $export = require('./_export') + , $task = require('./_task'); +$export($export.G + $export.B, { + setImmediate: $task.set, + clearImmediate: $task.clear +}); +},{"./_export":44,"./_task":54}],57:[function(require,module,exports){ +(function (global){ +'use strict'; +var Mutation = global.MutationObserver || global.WebKitMutationObserver; + +var scheduleDrain; + +{ + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + scheduleDrain = function () { + element.data = (called = ++called % 2); + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + + // Create a + + - - +
    - -
    - - - - - - - -
    - - -
    -

    ACF (Velocity) 0.5.0-SNAPSHOT API

    -
    -
    - - - - - - - - - - - - - - - - - - - - -
    Packages 
    PackageDescription
    co.aikar.commands 
    co.aikar.commands.contexts 
    co.aikar.commands.velocity.contexts 
    -
    - -
    - - - - - - - -
    - - -

    Copyright © 2019. All rights reserved.

    +

    index.html

    +
    diff --git a/docs/acf-velocity/overview-tree.html b/docs/acf-velocity/overview-tree.html index 6f471d14..96d62236 100644 --- a/docs/acf-velocity/overview-tree.html +++ b/docs/acf-velocity/overview-tree.html @@ -1,12 +1,21 @@ - + - Class Hierarchy (ACF (Velocity) 0.5.0-SNAPSHOT API) + + + + + + + + +var pathtoroot = "./"; +var useModuleDirectories = true; +loadScripts(document, 'script'); +
    + +
    +

    Hierarchy For All Packages

    Package Hierarchies: @@ -78,85 +102,92 @@
    +

    Class Hierarchy

    +
    +

    Enum Hierarchy

    +
    +
    + diff --git a/docs/acf-velocity/package-search-index.js b/docs/acf-velocity/package-search-index.js new file mode 100644 index 00000000..34436d56 --- /dev/null +++ b/docs/acf-velocity/package-search-index.js @@ -0,0 +1 @@ +packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"co.aikar.commands"},{"l":"co.aikar.commands.contexts"},{"l":"co.aikar.commands.velocity.contexts"}] \ No newline at end of file diff --git a/docs/acf-velocity/package-search-index.zip b/docs/acf-velocity/package-search-index.zip new file mode 100644 index 00000000..1cc05a98 Binary files /dev/null and b/docs/acf-velocity/package-search-index.zip differ diff --git a/docs/acf-velocity/resources/glass.png b/docs/acf-velocity/resources/glass.png new file mode 100644 index 00000000..a7f591f4 Binary files /dev/null and b/docs/acf-velocity/resources/glass.png differ diff --git a/docs/acf-velocity/resources/x.png b/docs/acf-velocity/resources/x.png new file mode 100644 index 00000000..30548a75 Binary files /dev/null and b/docs/acf-velocity/resources/x.png differ diff --git a/docs/acf-velocity/script.js b/docs/acf-velocity/script.js index b3463569..0eaaf535 100644 --- a/docs/acf-velocity/script.js +++ b/docs/acf-velocity/script.js @@ -1,9 +1,114 @@ -function show(type) -{ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var moduleSearchIndex; +var packageSearchIndex; +var typeSearchIndex; +var memberSearchIndex; +var tagSearchIndex; +function loadScripts(doc, tag) { + createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); + if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || + window.navigator.userAgent.indexOf('Edge/') > 0) { + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); + } + createElem(doc, tag, 'search.js'); + + $.get(pathtoroot + "module-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + moduleSearchIndex = JSON.parse(zip.file("module-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "package-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + packageSearchIndex = JSON.parse(zip.file("package-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "type-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + typeSearchIndex = JSON.parse(zip.file("type-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "member-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + memberSearchIndex = JSON.parse(zip.file("member-search-index.json").asText()); + }); + }); + $.get(pathtoroot + "tag-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) { + var zip = new JSZip(data); + zip.load(data); + tagSearchIndex = JSON.parse(zip.file("tag-search-index.json").asText()); + }); + }); + if (!moduleSearchIndex) { + createElem(doc, tag, 'module-search-index.js'); + } + if (!packageSearchIndex) { + createElem(doc, tag, 'package-search-index.js'); + } + if (!typeSearchIndex) { + createElem(doc, tag, 'type-search-index.js'); + } + if (!memberSearchIndex) { + createElem(doc, tag, 'member-search-index.js'); + } + if (!tagSearchIndex) { + createElem(doc, tag, 'tag-search-index.js'); + } + $(window).resize(function() { + $('.navPadding').css('padding-top', $('.fixedNav').css("height")); + }); +} + +function createElem(doc, tag, path) { + var script = doc.createElement(tag); + var scriptElement = doc.getElementsByTagName(tag)[0]; + script.src = pathtoroot + path; + scriptElement.parentNode.insertBefore(script, scriptElement); +} + +function show(type) { count = 0; - for (var key in methods) { + for (var key in data) { var row = document.getElementById(key); - if ((methods[key] & type) != 0) { + if ((data[key] & type) !== 0) { row.style.display = ''; row.className = (count++ % 2) ? rowColor : altColor; } @@ -13,8 +118,7 @@ function show(type) updateTabs(type); } -function updateTabs(type) -{ +function updateTabs(type) { for (var value in tabs) { var sNode = document.getElementById(tabs[value][0]); var spanNode = sNode.firstChild; @@ -28,3 +132,8 @@ function updateTabs(type) } } } + +function updateModuleFrame(pFrame, cFrame) { + top.packageFrame.location = pFrame; + top.classFrame.location = cFrame; +} diff --git a/docs/acf-velocity/search.js b/docs/acf-velocity/search.js new file mode 100644 index 00000000..b773531b --- /dev/null +++ b/docs/acf-velocity/search.js @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var noResult = {l: "No results found"}; +var catModules = "Modules"; +var catPackages = "Packages"; +var catTypes = "Types"; +var catMembers = "Members"; +var catSearchTags = "SearchTags"; +var highlight = "$&"; +var camelCaseRegexp = ""; +var secondaryMatcher = ""; +function getHighlightedText(item) { + var ccMatcher = new RegExp(camelCaseRegexp); + var label = item.replace(ccMatcher, highlight); + if (label === item) { + label = item.replace(secondaryMatcher, highlight); + } + return label; +} +function getURLPrefix(ui) { + var urlPrefix=""; + if (useModuleDirectories) { + var slash = "/"; + if (ui.item.category === catModules) { + return ui.item.l + slash; + } else if (ui.item.category === catPackages && ui.item.m) { + return ui.item.m + slash; + } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { + $.each(packageSearchIndex, function(index, item) { + if (ui.item.p == item.l) { + urlPrefix = item.m + slash; + } + }); + return urlPrefix; + } else { + return urlPrefix; + } + } + return urlPrefix; +} +var watermark = 'Search'; +$(function() { + $("#search").val(''); + $("#search").prop("disabled", false); + $("#reset").prop("disabled", false); + $("#search").val(watermark).addClass('watermark'); + $("#search").blur(function() { + if ($(this).val().length == 0) { + $(this).val(watermark).addClass('watermark'); + } + }); + $("#search").on('click keydown', function() { + if ($(this).val() == watermark) { + $(this).val('').removeClass('watermark'); + } + }); + $("#reset").click(function() { + $("#search").val(''); + $("#search").focus(); + }); + $("#search").focus(); + $("#search")[0].setSelectionRange(0, 0); +}); +$.widget("custom.catcomplete", $.ui.autocomplete, { + _create: function() { + this._super(); + this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)"); + }, + _renderMenu: function(ul, items) { + var rMenu = this, + currentCategory = ""; + rMenu.menu.bindings = $(); + $.each(items, function(index, item) { + var li; + if (item.l !== noResult.l && item.category !== currentCategory) { + ul.append("
  • " + item.category + "
  • "); + currentCategory = item.category; + } + li = rMenu._renderItemData(ul, item); + if (item.category) { + li.attr("aria-label", item.category + " : " + item.l); + li.attr("class", "resultItem"); + } else { + li.attr("aria-label", item.l); + li.attr("class", "resultItem"); + } + }); + }, + _renderItem: function(ul, item) { + var label = ""; + if (item.category === catModules) { + label = getHighlightedText(item.l); + } else if (item.category === catPackages) { + label = (item.m) + ? getHighlightedText(item.m + "/" + item.l) + : getHighlightedText(item.l); + } else if (item.category === catTypes) { + label = (item.p) + ? getHighlightedText(item.p + "." + item.l) + : getHighlightedText(item.l); + } else if (item.category === catMembers) { + label = getHighlightedText(item.p + "." + (item.c + "." + item.l)); + } else if (item.category === catSearchTags) { + label = getHighlightedText(item.l); + } else { + label = item.l; + } + var li = $("
  • ").appendTo(ul); + var div = $("
    ").appendTo(li); + if (item.category === catSearchTags) { + if (item.d) { + div.html(label + " (" + item.h + ")
    " + + item.d + "
    "); + } else { + div.html(label + " (" + item.h + ")"); + } + } else { + div.html(label); + } + return li; + } +}); +$(function() { + $("#search").catcomplete({ + minLength: 1, + delay: 100, + source: function(request, response) { + var result = new Array(); + var presult = new Array(); + var tresult = new Array(); + var mresult = new Array(); + var tgresult = new Array(); + var secondaryresult = new Array(); + var displayCount = 0; + var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i"); + camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)"); + var camelCaseMatcher = new RegExp("^" + camelCaseRegexp); + secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); + + // Return the nested innermost name from the specified object + function nestedName(e) { + return e.l.substring(e.l.lastIndexOf(".") + 1); + } + + function concatResults(a1, a2) { + a1 = a1.concat(a2); + a2.length = 0; + return a1; + } + + if (moduleSearchIndex) { + var mdleCount = 0; + $.each(moduleSearchIndex, function(index, item) { + item.category = catModules; + if (exactMatcher.test(item.l)) { + result.push(item); + mdleCount++; + } else if (camelCaseMatcher.test(item.l)) { + result.push(item); + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + displayCount = mdleCount; + result = concatResults(result, secondaryresult); + } + if (packageSearchIndex) { + var pCount = 0; + var pkg = ""; + $.each(packageSearchIndex, function(index, item) { + item.category = catPackages; + pkg = (item.m) + ? (item.m + "/" + item.l) + : item.l; + if (exactMatcher.test(item.l)) { + presult.push(item); + pCount++; + } else if (camelCaseMatcher.test(pkg)) { + presult.push(item); + } else if (secondaryMatcher.test(pkg)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(presult, secondaryresult)); + displayCount = (pCount > displayCount) ? pCount : displayCount; + } + if (typeSearchIndex) { + var tCount = 0; + $.each(typeSearchIndex, function(index, item) { + item.category = catTypes; + var s = nestedName(item); + if (exactMatcher.test(s)) { + tresult.push(item); + tCount++; + } else if (camelCaseMatcher.test(s)) { + tresult.push(item); + } else if (secondaryMatcher.test(item.p + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tresult, secondaryresult)); + displayCount = (tCount > displayCount) ? tCount : displayCount; + } + if (memberSearchIndex) { + var mCount = 0; + $.each(memberSearchIndex, function(index, item) { + item.category = catMembers; + var s = nestedName(item); + if (exactMatcher.test(s)) { + mresult.push(item); + mCount++; + } else if (camelCaseMatcher.test(s)) { + mresult.push(item); + } else if (secondaryMatcher.test(item.c + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(mresult, secondaryresult)); + displayCount = (mCount > displayCount) ? mCount : displayCount; + } + if (tagSearchIndex) { + var tgCount = 0; + $.each(tagSearchIndex, function(index, item) { + item.category = catSearchTags; + if (exactMatcher.test(item.l)) { + tgresult.push(item); + tgCount++; + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tgresult, secondaryresult)); + displayCount = (tgCount > displayCount) ? tgCount : displayCount; + } + displayCount = (displayCount > 500) ? displayCount : 500; + var counter = function() { + var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0}; + var f = function(item) { + count[item.category] += 1; + return (count[item.category] <= displayCount); + }; + return f; + }(); + response(result.filter(counter)); + }, + response: function(event, ui) { + if (!ui.content.length) { + ui.content.push(noResult); + } else { + $("#search").empty(); + } + }, + autoFocus: true, + position: { + collision: "flip" + }, + select: function(event, ui) { + if (ui.item.l !== noResult.l) { + var url = getURLPrefix(ui); + if (ui.item.category === catModules) { + if (useModuleDirectories) { + url += "module-summary.html"; + } else { + url = ui.item.l + "-summary.html"; + } + } else if (ui.item.category === catPackages) { + if (ui.item.url) { + url = ui.item.url; + } else { + url += ui.item.l.replace(/\./g, '/') + "/package-summary.html"; + } + } else if (ui.item.category === catTypes) { + if (ui.item.url) { + url = ui.item.url; + } else if (ui.item.p === "") { + url += ui.item.l + ".html"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; + } + } else if (ui.item.category === catMembers) { + if (ui.item.p === "") { + url += ui.item.c + ".html" + "#"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; + } + if (ui.item.url) { + url += ui.item.url; + } else { + url += ui.item.l; + } + } else if (ui.item.category === catSearchTags) { + url += ui.item.u; + } + if (top !== window) { + parent.classFrame.location = pathtoroot + url; + } else { + window.location.href = pathtoroot + url; + } + $("#search").focus(); + } + } + }); +}); diff --git a/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityListener.html b/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityListener.html index ccc9e1d8..88953ff6 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityListener.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityListener.html @@ -1,56 +1,57 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import java.util.concurrent.TimeUnit;
    -004
    -005import com.velocitypowered.api.event.Subscribe;
    -006import com.velocitypowered.api.event.connection.DisconnectEvent;
    -007import com.velocitypowered.api.event.connection.PostLoginEvent;
    -008import com.velocitypowered.api.event.player.PlayerSettingsChangedEvent;
    -009import com.velocitypowered.api.plugin.PluginContainer;
    -010import com.velocitypowered.api.proxy.Player;
    -011import com.velocitypowered.api.proxy.ProxyServer;
    -012
    -013public class ACFVelocityListener {
    -014
    -015    private final VelocityCommandManager manager;
    -016    private final PluginContainer plugin;
    -017    private final ProxyServer proxy;
    -018
    -019    public ACFVelocityListener(VelocityCommandManager manager, PluginContainer plugin, ProxyServer proxy) {
    -020        this.manager = manager;
    -021        this.plugin = plugin;
    -022        this.proxy = proxy;
    -023    }
    -024
    -025    @Subscribe
    -026    public void onPlayerJoin(PostLoginEvent loginEvent) {
    -027        Player player = loginEvent.getPlayer();
    -028
    -029        // the client settings are sent after a successful login
    -030        Runnable task = () -> manager.readLocale(player);
    -031        proxy.getScheduler().buildTask(plugin, task).delay(1, TimeUnit.SECONDS).schedule();
    -032    }
    -033
    -034    @Subscribe
    -035    public void onDisconnect(DisconnectEvent disconnectEvent) {
    -036        // cleanup
    -037        Player player = disconnectEvent.getPlayer();
    -038        manager.issuersLocale.remove(player.getUniqueId());
    -039    }
    -040
    -041    @Subscribe
    -042    public void onSettingsChange(PlayerSettingsChangedEvent settingsEvent) {
    -043        manager.setIssuerLocale(settingsEvent.getPlayer(), settingsEvent.getPlayer().getPlayerSettings().getLocale());
    -044    }
    -045}
    +
    001package co.aikar.commands;
    +002
    +003import java.util.concurrent.TimeUnit;
    +004
    +005import com.velocitypowered.api.event.Subscribe;
    +006import com.velocitypowered.api.event.connection.DisconnectEvent;
    +007import com.velocitypowered.api.event.connection.PostLoginEvent;
    +008import com.velocitypowered.api.event.player.PlayerSettingsChangedEvent;
    +009import com.velocitypowered.api.plugin.PluginContainer;
    +010import com.velocitypowered.api.proxy.Player;
    +011import com.velocitypowered.api.proxy.ProxyServer;
    +012
    +013public class ACFVelocityListener {
    +014
    +015    private final VelocityCommandManager manager;
    +016    private final PluginContainer plugin;
    +017    private final ProxyServer proxy;
    +018
    +019    public ACFVelocityListener(VelocityCommandManager manager, PluginContainer plugin, ProxyServer proxy) {
    +020        this.manager = manager;
    +021        this.plugin = plugin;
    +022        this.proxy = proxy;
    +023    }
    +024
    +025    @Subscribe
    +026    public void onPlayerJoin(PostLoginEvent loginEvent) {
    +027        Player player = loginEvent.getPlayer();
    +028
    +029        // the client settings are sent after a successful login
    +030        Runnable task = () -> manager.readLocale(player);
    +031        proxy.getScheduler().buildTask(plugin, task).delay(1, TimeUnit.SECONDS).schedule();
    +032    }
    +033
    +034    @Subscribe
    +035    public void onDisconnect(DisconnectEvent disconnectEvent) {
    +036        // cleanup
    +037        Player player = disconnectEvent.getPlayer();
    +038        manager.issuersLocale.remove(player.getUniqueId());
    +039    }
    +040
    +041    @Subscribe
    +042    public void onSettingsChange(PlayerSettingsChangedEvent settingsEvent) {
    +043        manager.setIssuerLocale(settingsEvent.getPlayer(), settingsEvent.getPlayer().getPlayerSettings().getLocale());
    +044    }
    +045}
     
     
     
    @@ -113,5 +114,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityUtil.html b/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityUtil.html index f551aae8..7d76d5c6 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityUtil.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/ACFVelocityUtil.html @@ -1,91 +1,92 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import java.util.ArrayList;
    -004import java.util.Collection;
    -005import java.util.Collections;
    -006import java.util.List;
    -007import java.util.Optional;
    -008import java.util.stream.Collectors;
    -009
    -010import com.velocitypowered.api.command.CommandSource;
    -011import com.velocitypowered.api.proxy.Player;
    -012import com.velocitypowered.api.proxy.ProxyServer;
    -013
    -014import net.kyori.text.TextComponent;
    -015import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
    -016
    -017public class ACFVelocityUtil {
    -018
    -019    @SuppressWarnings("deprecation")
    -020    public static TextComponent color(String message) {
    -021        return LegacyComponentSerializer.legacy().deserialize(message);
    -022    }
    -023
    -024    public static Player findPlayerSmart(ProxyServer server, CommandIssuer issuer, String search) {
    -025        CommandSource requester = issuer.getIssuer();
    -026        String name = ACFUtil.replace(search, ":confirm", "");
    -027        if (!isValidName(name)) {
    -028            issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
    -029            return null;
    -030        }
    -031
    -032        List<Player> matches = new ArrayList<>(matchPlayer(server, name));
    -033
    -034        if (matches.size() > 1) {
    -035            String allMatches = matches.stream().map(Player::getUsername).collect(Collectors.joining(", "));
    -036            issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH, "{search}", name, "{all}", allMatches);
    -037            return null;
    -038        }
    -039
    -040        if (matches.isEmpty()) {
    -041            issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name);
    -042            return null;
    -043        }
    -044
    -045        return matches.get(0);
    -046    }
    -047
    -048    /*
    -049     * Original code written by md_5
    -050     *
    -051     * Modified to work with Velocity by Crypnotic
    -052     */
    -053    private static Collection<Player> matchPlayer(ProxyServer server, final String partialName) {
    -054        // A better error message might be nice. This just mimics the previous output
    -055        if (partialName == null) {
    -056            throw new NullPointerException("partialName");
    -057        }
    -058
    -059        Optional<Player> exactMatch = server.getPlayer(partialName);
    -060        //noinspection OptionalIsPresent
    -061        if (exactMatch.isPresent()) {
    -062            return Collections.singleton(exactMatch.get());
    -063        }
    -064
    -065        return server.getAllPlayers().stream()
    -066                .filter(player -> player.getUsername().regionMatches(true, 0, partialName, 0, partialName.length()))
    -067                .collect(Collectors.toList());
    -068    }
    -069
    -070    public static boolean isValidName(String name) {
    -071        return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches();
    -072    }
    -073
    -074    public static <T> T validate(T object, String message, Object... values) {
    -075        if (object == null) {
    -076            throw new NullPointerException(String.format(message, values));
    -077        }
    -078        return object;
    -079    }
    -080}
    +
    001package co.aikar.commands;
    +002
    +003import java.util.ArrayList;
    +004import java.util.Collection;
    +005import java.util.Collections;
    +006import java.util.List;
    +007import java.util.Optional;
    +008import java.util.stream.Collectors;
    +009
    +010import com.velocitypowered.api.command.CommandSource;
    +011import com.velocitypowered.api.proxy.Player;
    +012import com.velocitypowered.api.proxy.ProxyServer;
    +013
    +014import net.kyori.text.TextComponent;
    +015import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
    +016
    +017public class ACFVelocityUtil {
    +018
    +019    @SuppressWarnings("deprecation")
    +020    public static TextComponent color(String message) {
    +021        return LegacyComponentSerializer.legacy().deserialize(message);
    +022    }
    +023
    +024    public static Player findPlayerSmart(ProxyServer server, CommandIssuer issuer, String search) {
    +025        CommandSource requester = issuer.getIssuer();
    +026        String name = ACFUtil.replace(search, ":confirm", "");
    +027        if (!isValidName(name)) {
    +028            issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name);
    +029            return null;
    +030        }
    +031
    +032        List<Player> matches = new ArrayList<>(matchPlayer(server, name));
    +033
    +034        if (matches.size() > 1) {
    +035            String allMatches = matches.stream().map(Player::getUsername).collect(Collectors.joining(", "));
    +036            issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH, "{search}", name, "{all}", allMatches);
    +037            return null;
    +038        }
    +039
    +040        if (matches.isEmpty()) {
    +041            issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name);
    +042            return null;
    +043        }
    +044
    +045        return matches.get(0);
    +046    }
    +047
    +048    /*
    +049     * Original code written by md_5
    +050     *
    +051     * Modified to work with Velocity by Crypnotic
    +052     */
    +053    private static Collection<Player> matchPlayer(ProxyServer server, final String partialName) {
    +054        // A better error message might be nice. This just mimics the previous output
    +055        if (partialName == null) {
    +056            throw new NullPointerException("partialName");
    +057        }
    +058
    +059        Optional<Player> exactMatch = server.getPlayer(partialName);
    +060        //noinspection OptionalIsPresent
    +061        if (exactMatch.isPresent()) {
    +062            return Collections.singleton(exactMatch.get());
    +063        }
    +064
    +065        return server.getAllPlayers().stream()
    +066                .filter(player -> player.getUsername().regionMatches(true, 0, partialName, 0, partialName.length()))
    +067                .collect(Collectors.toList());
    +068    }
    +069
    +070    public static boolean isValidName(String name) {
    +071        return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches();
    +072    }
    +073
    +074    public static <T> T validate(T object, String message, Object... values) {
    +075        if (object == null) {
    +076            throw new NullPointerException(String.format(message, values));
    +077        }
    +078        return object;
    +079    }
    +080}
     
     
     
    @@ -148,5 +149,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/MinecraftMessageKeys.html b/docs/acf-velocity/src-html/co/aikar/commands/MinecraftMessageKeys.html index 7b2b5484..14e94058 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/MinecraftMessageKeys.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/MinecraftMessageKeys.html @@ -1,29 +1,32 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import co.aikar.locales.MessageKey;
    -004import co.aikar.locales.MessageKeyProvider;
    -005
    -006public enum MinecraftMessageKeys implements MessageKeyProvider {
    -007    USERNAME_TOO_SHORT,
    -008    IS_NOT_A_VALID_NAME,
    -009    MULTIPLE_PLAYERS_MATCH,
    -010    NO_PLAYER_FOUND_SERVER,
    -011    NO_PLAYER_FOUND
    -012    ;
    -013
    -014    private final MessageKey key = MessageKey.of("acf-minecraft." + this.name().toLowerCase());
    -015    public MessageKey getMessageKey() {
    -016        return key;
    -017    }
    -018}
    +
    001package co.aikar.commands;
    +002
    +003import co.aikar.locales.MessageKey;
    +004import co.aikar.locales.MessageKeyProvider;
    +005
    +006import java.util.Locale;
    +007
    +008public enum MinecraftMessageKeys implements MessageKeyProvider {
    +009    USERNAME_TOO_SHORT,
    +010    IS_NOT_A_VALID_NAME,
    +011    MULTIPLE_PLAYERS_MATCH,
    +012    NO_PLAYER_FOUND_SERVER,
    +013    NO_PLAYER_FOUND;
    +014
    +015    private final MessageKey key = MessageKey.of("acf-minecraft." + this.name().toLowerCase(Locale.ENGLISH));
    +016
    +017    public MessageKey getMessageKey() {
    +018        return key;
    +019    }
    +020}
     
     
     
    @@ -86,5 +89,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletionContext.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletionContext.html index df04ecd5..4dd597fd 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletionContext.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletionContext.html @@ -1,53 +1,54 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import com.velocitypowered.api.command.CommandSource;
    -027import com.velocitypowered.api.proxy.Player;
    -028
    -029public class VelocityCommandCompletionContext extends CommandCompletionContext<VelocityCommandIssuer> {
    -030
    -031    VelocityCommandCompletionContext(RegisteredCommand command, VelocityCommandIssuer issuer, String input, String config, String[] args) {
    -032        super(command, issuer, input, config, args);
    -033    }
    -034
    -035    public CommandSource getSender() {
    -036        return this.getIssuer().getIssuer();
    -037    }
    -038
    -039    public Player getPlayer() {
    -040        return this.issuer.getPlayer();
    -041    }
    -042}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import com.velocitypowered.api.command.CommandSource;
    +027import com.velocitypowered.api.proxy.Player;
    +028
    +029public class VelocityCommandCompletionContext extends CommandCompletionContext<VelocityCommandIssuer> {
    +030
    +031    VelocityCommandCompletionContext(RegisteredCommand command, VelocityCommandIssuer issuer, String input, String config, String[] args) {
    +032        super(command, issuer, input, config, args);
    +033    }
    +034
    +035    public CommandSource getSender() {
    +036        return this.getIssuer().getIssuer();
    +037    }
    +038
    +039    public Player getPlayer() {
    +040        return this.issuer.getPlayer();
    +041    }
    +042}
     
     
     
    @@ -110,5 +111,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletions.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletions.html index 2e17260d..beadb381 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletions.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandCompletions.html @@ -1,88 +1,89 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import java.util.ArrayList;
    -027import java.util.Arrays;
    -028import java.util.Set;
    -029import java.util.stream.Collectors;
    -030import java.util.stream.Stream;
    -031
    -032import com.velocitypowered.api.command.CommandSource;
    -033import com.velocitypowered.api.proxy.Player;
    -034import com.velocitypowered.api.proxy.ProxyServer;
    -035
    -036import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
    -037import net.kyori.text.format.TextColor;
    -038import net.kyori.text.format.TextDecoration;
    -039import net.kyori.text.format.TextFormat;
    -040
    -041public class VelocityCommandCompletions extends CommandCompletions<VelocityCommandCompletionContext> {
    -042
    -043    public VelocityCommandCompletions(ProxyServer server, CommandManager manager) {
    -044        super(manager);
    -045        registerAsyncCompletion("chatcolors", c -> {
    -046            Stream<TextFormat> colors = Stream.of(TextColor.values());
    -047            if (!c.hasConfig("colorsonly")) {
    -048                colors = Stream.concat(colors, Stream.of(TextDecoration.values()));
    -049            }
    -050            String filter = c.getConfig("filter");
    -051            if (filter != null) {
    -052                Set<String> filters = Arrays.stream(ACFPatterns.COLON.split(filter)).map(ACFUtil::simplifyString)
    -053                        .collect(Collectors.toSet());
    -054
    -055                colors = colors.filter(color -> filters.contains(ACFUtil.simplifyString(color.toString())));
    -056            }
    -057
    -058            return colors.map(color -> ACFUtil.simplifyString(color.toString())).collect(Collectors.toList());
    -059        });
    -060        registerCompletion("players", c -> {
    -061            CommandSource sender = c.getSender();
    -062            ACFVelocityUtil.validate(sender, "Sender cannot be null");
    -063            String input = c.getInput();
    -064
    -065            ArrayList<String> matchedPlayers = new ArrayList<>();
    -066            for (Player player : server.getAllPlayers()) {
    -067                String name = player.getUsername();
    -068                if (ApacheCommonsLangUtil.startsWithIgnoreCase(name, input)) {
    -069                    matchedPlayers.add(name);
    -070                }
    -071            }
    -072
    -073            matchedPlayers.sort(String.CASE_INSENSITIVE_ORDER);
    -074            return matchedPlayers;
    -075        });
    -076    }
    -077}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import java.util.ArrayList;
    +027import java.util.Arrays;
    +028import java.util.Set;
    +029import java.util.stream.Collectors;
    +030import java.util.stream.Stream;
    +031
    +032import com.velocitypowered.api.command.CommandSource;
    +033import com.velocitypowered.api.proxy.Player;
    +034import com.velocitypowered.api.proxy.ProxyServer;
    +035
    +036import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil;
    +037import net.kyori.text.format.TextColor;
    +038import net.kyori.text.format.TextDecoration;
    +039import net.kyori.text.format.TextFormat;
    +040
    +041public class VelocityCommandCompletions extends CommandCompletions<VelocityCommandCompletionContext> {
    +042
    +043    public VelocityCommandCompletions(ProxyServer server, CommandManager manager) {
    +044        super(manager);
    +045        registerAsyncCompletion("chatcolors", c -> {
    +046            Stream<TextFormat> colors = Stream.of(TextColor.values());
    +047            if (!c.hasConfig("colorsonly")) {
    +048                colors = Stream.concat(colors, Stream.of(TextDecoration.values()));
    +049            }
    +050            String filter = c.getConfig("filter");
    +051            if (filter != null) {
    +052                Set<String> filters = Arrays.stream(ACFPatterns.COLON.split(filter)).map(ACFUtil::simplifyString)
    +053                        .collect(Collectors.toSet());
    +054
    +055                colors = colors.filter(color -> filters.contains(ACFUtil.simplifyString(color.toString())));
    +056            }
    +057
    +058            return colors.map(color -> ACFUtil.simplifyString(color.toString())).collect(Collectors.toList());
    +059        });
    +060        registerCompletion("players", c -> {
    +061            CommandSource sender = c.getSender();
    +062            ACFVelocityUtil.validate(sender, "Sender cannot be null");
    +063            String input = c.getInput();
    +064
    +065            ArrayList<String> matchedPlayers = new ArrayList<>();
    +066            for (Player player : server.getAllPlayers()) {
    +067                String name = player.getUsername();
    +068                if (ApacheCommonsLangUtil.startsWithIgnoreCase(name, input)) {
    +069                    matchedPlayers.add(name);
    +070                }
    +071            }
    +072
    +073            matchedPlayers.sort(String.CASE_INSENSITIVE_ORDER);
    +074            return matchedPlayers;
    +075        });
    +076    }
    +077}
     
     
     
    @@ -145,5 +146,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandContexts.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandContexts.html index e5612b08..c62d9afb 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandContexts.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandContexts.html @@ -1,103 +1,104 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import java.util.stream.Collectors;
    -027import java.util.stream.Stream;
    -028
    -029import com.velocitypowered.api.command.CommandSource;
    -030import com.velocitypowered.api.proxy.Player;
    -031import com.velocitypowered.api.proxy.ProxyServer;
    -032
    -033import co.aikar.commands.velocity.contexts.OnlinePlayer;
    -034import net.kyori.text.format.TextColor;
    -035import net.kyori.text.format.TextDecoration;
    -036import net.kyori.text.format.TextFormat;
    -037import org.jetbrains.annotations.Nullable;
    -038
    -039public class VelocityCommandContexts extends CommandContexts<VelocityCommandExecutionContext> {
    -040
    -041    VelocityCommandContexts(ProxyServer server, CommandManager manager) {
    -042        super(manager);
    -043        registerContext(OnlinePlayer.class, (c) -> getOnlinePlayer(server, c));
    -044        registerContext(co.aikar.commands.contexts.OnlinePlayer.class, c -> {
    -045            OnlinePlayer onlinePlayer = getOnlinePlayer(server, c);
    -046            return onlinePlayer != null ? new co.aikar.commands.contexts.OnlinePlayer(onlinePlayer.getPlayer()) : null;
    -047        });
    -048        registerIssuerAwareContext(CommandSource.class, VelocityCommandExecutionContext::getSender);
    -049        registerIssuerAwareContext(Player.class, (c) -> {
    -050            Player proxiedPlayer = c.getSender() instanceof Player ? (Player) c.getSender() : null;
    -051            if (proxiedPlayer == null && !c.isOptional()) {
    -052                throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
    -053            }
    -054            return proxiedPlayer;
    -055        });
    -056
    -057        registerContext(TextFormat.class, c -> {
    -058            String first = c.popFirstArg();
    -059            Stream<TextFormat> colors = Stream.of(TextColor.values());
    -060            if (!c.hasFlag("colorsonly")) {
    -061                colors = Stream.concat(colors, Stream.of(TextDecoration.values()));
    -062            }
    -063            String filter = c.getFlagValue("filter", (String) null);
    -064            if (filter != null) {
    -065                filter = ACFUtil.simplifyString(filter);
    -066                String finalFilter = filter;
    -067                colors = colors.filter(color -> finalFilter.equals(ACFUtil.simplifyString(color.toString())));
    -068            }
    -069
    -070            TextColor match = ACFUtil.simpleMatch(TextColor.class, first);
    -071            if (match == null) {
    -072                String valid = colors.map(color -> "<c2>" + ACFUtil.simplifyString(color.toString()) + "</c2>")
    -073                        .collect(Collectors.joining("<c1>,</c1> "));
    -074
    -075                throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
    -076            }
    -077            return match;
    -078        });
    -079    }
    -080
    -081    @Nullable
    -082    private OnlinePlayer getOnlinePlayer(ProxyServer server, VelocityCommandExecutionContext c) throws InvalidCommandArgument {
    -083        Player proxiedPlayer = ACFVelocityUtil.findPlayerSmart(server, c.getIssuer(), c.popFirstArg());
    -084        if (proxiedPlayer == null) {
    -085            if (c.isOptional()) {
    -086                return null;
    -087            }
    -088            throw new InvalidCommandArgument(false);
    -089        }
    -090        return new OnlinePlayer(proxiedPlayer);
    -091    }
    -092}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import java.util.stream.Collectors;
    +027import java.util.stream.Stream;
    +028
    +029import com.velocitypowered.api.command.CommandSource;
    +030import com.velocitypowered.api.proxy.Player;
    +031import com.velocitypowered.api.proxy.ProxyServer;
    +032
    +033import co.aikar.commands.velocity.contexts.OnlinePlayer;
    +034import net.kyori.text.format.TextColor;
    +035import net.kyori.text.format.TextDecoration;
    +036import net.kyori.text.format.TextFormat;
    +037import org.jetbrains.annotations.Nullable;
    +038
    +039public class VelocityCommandContexts extends CommandContexts<VelocityCommandExecutionContext> {
    +040
    +041    VelocityCommandContexts(ProxyServer server, CommandManager manager) {
    +042        super(manager);
    +043        registerContext(OnlinePlayer.class, (c) -> getOnlinePlayer(server, c));
    +044        registerContext(co.aikar.commands.contexts.OnlinePlayer.class, c -> {
    +045            OnlinePlayer onlinePlayer = getOnlinePlayer(server, c);
    +046            return onlinePlayer != null ? new co.aikar.commands.contexts.OnlinePlayer(onlinePlayer.getPlayer()) : null;
    +047        });
    +048        registerIssuerAwareContext(CommandSource.class, VelocityCommandExecutionContext::getSender);
    +049        registerIssuerAwareContext(Player.class, (c) -> {
    +050            Player proxiedPlayer = c.getSender() instanceof Player ? (Player) c.getSender() : null;
    +051            if (proxiedPlayer == null && !c.isOptional()) {
    +052                throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE, false);
    +053            }
    +054            return proxiedPlayer;
    +055        });
    +056
    +057        registerContext(TextFormat.class, c -> {
    +058            String first = c.popFirstArg();
    +059            Stream<TextFormat> colors = Stream.of(TextColor.values());
    +060            if (!c.hasFlag("colorsonly")) {
    +061                colors = Stream.concat(colors, Stream.of(TextDecoration.values()));
    +062            }
    +063            String filter = c.getFlagValue("filter", (String) null);
    +064            if (filter != null) {
    +065                filter = ACFUtil.simplifyString(filter);
    +066                String finalFilter = filter;
    +067                colors = colors.filter(color -> finalFilter.equals(ACFUtil.simplifyString(color.toString())));
    +068            }
    +069
    +070            TextColor match = ACFUtil.simpleMatch(TextColor.class, first);
    +071            if (match == null) {
    +072                String valid = colors.map(color -> "<c2>" + ACFUtil.simplifyString(color.toString()) + "</c2>")
    +073                        .collect(Collectors.joining("<c1>,</c1> "));
    +074
    +075                throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, "{valid}", valid);
    +076            }
    +077            return match;
    +078        });
    +079    }
    +080
    +081    @Nullable
    +082    private OnlinePlayer getOnlinePlayer(ProxyServer server, VelocityCommandExecutionContext c) throws InvalidCommandArgument {
    +083        Player proxiedPlayer = ACFVelocityUtil.findPlayerSmart(server, c.getIssuer(), c.popFirstArg());
    +084        if (proxiedPlayer == null) {
    +085            if (c.isOptional()) {
    +086                return null;
    +087            }
    +088            throw new InvalidCommandArgument(false);
    +089        }
    +090        return new OnlinePlayer(proxiedPlayer);
    +091    }
    +092}
     
     
     
    @@ -160,5 +161,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandExecutionContext.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandExecutionContext.html index 90e742d3..fa507161 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandExecutionContext.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandExecutionContext.html @@ -1,33 +1,34 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import java.util.List;
    -004import java.util.Map;
    -005
    -006import com.velocitypowered.api.command.CommandSource;
    -007import com.velocitypowered.api.proxy.Player;
    -008
    -009public class VelocityCommandExecutionContext extends CommandExecutionContext<VelocityCommandExecutionContext, VelocityCommandIssuer> {
    -010
    -011    VelocityCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, VelocityCommandIssuer sender, List<String> args, int index, Map<String, Object> passedArgs) {
    -012        super(cmd, param, sender, args, index, passedArgs);
    -013    }
    -014
    -015    public CommandSource getSender() {
    -016        return this.issuer.getIssuer();
    -017    }
    -018
    -019    public Player getPlayer() {
    -020        return this.issuer.getPlayer();
    -021    }
    -022}
    +
    001package co.aikar.commands;
    +002
    +003import java.util.List;
    +004import java.util.Map;
    +005
    +006import com.velocitypowered.api.command.CommandSource;
    +007import com.velocitypowered.api.proxy.Player;
    +008
    +009public class VelocityCommandExecutionContext extends CommandExecutionContext<VelocityCommandExecutionContext, VelocityCommandIssuer> {
    +010
    +011    VelocityCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, VelocityCommandIssuer sender, List<String> args, int index, Map<String, Object> passedArgs) {
    +012        super(cmd, param, sender, args, index, passedArgs);
    +013    }
    +014
    +015    public CommandSource getSender() {
    +016        return this.issuer.getIssuer();
    +017    }
    +018
    +019    public Player getPlayer() {
    +020        return this.issuer.getPlayer();
    +021    }
    +022}
     
     
     
    @@ -90,5 +91,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandIssuer.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandIssuer.html index bbf78e39..7c26c75a 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandIssuer.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandIssuer.html @@ -1,109 +1,110 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import java.nio.charset.StandardCharsets;
    -027import java.util.Objects;
    -028import java.util.UUID;
    -029
    -030import org.jetbrains.annotations.NotNull;
    -031
    -032import com.velocitypowered.api.command.CommandSource;
    -033import com.velocitypowered.api.proxy.Player;
    -034
    -035public class VelocityCommandIssuer implements CommandIssuer {
    -036    private final VelocityCommandManager manager;
    -037    private final CommandSource source;
    -038
    -039    VelocityCommandIssuer(VelocityCommandManager manager, CommandSource source) {
    -040        this.manager = manager;
    -041        this.source = source;
    -042    }
    -043
    -044
    -045    @Override
    -046    public CommandSource getIssuer() {
    -047        return source;
    -048    }
    -049
    -050    public Player getPlayer() {
    -051        return isPlayer() ? (Player) source : null;
    -052    }
    -053
    -054    @Override
    -055    public CommandManager getManager() {
    -056        return manager;
    -057    }
    -058
    -059    @Override
    -060    public boolean isPlayer() {
    -061        return source instanceof Player;
    -062    }
    -063
    -064    @Override
    -065    public @NotNull UUID getUniqueId() {
    -066        if (isPlayer()) {
    -067            return ((Player) source).getUniqueId();
    -068        }
    -069
    -070        // TODO: Find a better solution for this
    -071        //generate a unique id based of the name (like for the console command sender)
    -072        return UUID.randomUUID();
    -073    }
    -074
    -075    @Override
    -076    public void sendMessageInternal(String message) {
    -077        source.sendMessage(ACFVelocityUtil.color(message));
    -078    }
    -079
    -080    @Override
    -081    public boolean hasPermission(String name) {
    -082        return source.hasPermission(name);
    -083    }
    -084
    -085
    -086    @Override
    -087    public boolean equals(Object o) {
    -088        if (this == o) return true;
    -089        if (o == null || getClass() != o.getClass()) return false;
    -090        VelocityCommandIssuer that = (VelocityCommandIssuer) o;
    -091        return Objects.equals(source, that.source);
    -092    }
    -093
    -094    @Override
    -095    public int hashCode() {
    -096        return Objects.hash(source);
    -097    }
    -098}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import java.nio.charset.StandardCharsets;
    +027import java.util.Objects;
    +028import java.util.UUID;
    +029
    +030import org.jetbrains.annotations.NotNull;
    +031
    +032import com.velocitypowered.api.command.CommandSource;
    +033import com.velocitypowered.api.proxy.Player;
    +034
    +035public class VelocityCommandIssuer implements CommandIssuer {
    +036    private final VelocityCommandManager manager;
    +037    private final CommandSource source;
    +038
    +039    VelocityCommandIssuer(VelocityCommandManager manager, CommandSource source) {
    +040        this.manager = manager;
    +041        this.source = source;
    +042    }
    +043
    +044
    +045    @Override
    +046    public CommandSource getIssuer() {
    +047        return source;
    +048    }
    +049
    +050    public Player getPlayer() {
    +051        return isPlayer() ? (Player) source : null;
    +052    }
    +053
    +054    @Override
    +055    public CommandManager getManager() {
    +056        return manager;
    +057    }
    +058
    +059    @Override
    +060    public boolean isPlayer() {
    +061        return source instanceof Player;
    +062    }
    +063
    +064    @Override
    +065    public @NotNull UUID getUniqueId() {
    +066        if (isPlayer()) {
    +067            return ((Player) source).getUniqueId();
    +068        }
    +069
    +070        // TODO: Find a better solution for this
    +071        //generate a unique id based of the name (like for the console command sender)
    +072        return UUID.randomUUID();
    +073    }
    +074
    +075    @Override
    +076    public void sendMessageInternal(String message) {
    +077        source.sendMessage(ACFVelocityUtil.color(message));
    +078    }
    +079
    +080    @Override
    +081    public boolean hasPermission(String name) {
    +082        return source.hasPermission(name);
    +083    }
    +084
    +085
    +086    @Override
    +087    public boolean equals(Object o) {
    +088        if (this == o) return true;
    +089        if (o == null || getClass() != o.getClass()) return false;
    +090        VelocityCommandIssuer that = (VelocityCommandIssuer) o;
    +091        return Objects.equals(source, that.source);
    +092    }
    +093
    +094    @Override
    +095    public int hashCode() {
    +096        return Objects.hash(source);
    +097    }
    +098}
     
     
     
    @@ -166,5 +167,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandManager.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandManager.html index 0c48c5e5..9d043858 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandManager.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityCommandManager.html @@ -1,240 +1,241 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import java.lang.reflect.Method;
    -027import java.util.Collection;
    -028import java.util.Collections;
    -029import java.util.HashMap;
    -030import java.util.List;
    -031import java.util.Locale;
    -032import java.util.Map;
    -033
    -034import org.slf4j.Logger;
    -035import org.slf4j.LoggerFactory;
    -036
    -037import com.velocitypowered.api.command.CommandSource;
    -038import com.velocitypowered.api.plugin.Plugin;
    -039import com.velocitypowered.api.plugin.PluginContainer;
    -040import com.velocitypowered.api.proxy.Player;
    -041import com.velocitypowered.api.proxy.ProxyServer;
    -042
    -043import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    -044import net.kyori.text.format.TextColor;
    -045
    -046public class VelocityCommandManager extends
    -047        CommandManager<CommandSource, VelocityCommandIssuer, TextColor, VelocityMessageFormatter, VelocityCommandExecutionContext, VelocityConditionContext> {
    -048
    -049    protected final ProxyServer proxy;
    -050    protected final PluginContainer plugin;
    -051    protected Map<String, VelocityRootCommand> registeredCommands = new HashMap<>();
    -052    protected VelocityCommandContexts contexts;
    -053    protected VelocityCommandCompletions completions;
    -054    protected VelocityLocales locales;
    -055
    -056    public VelocityCommandManager(ProxyServer proxy, Object plugin) {
    -057        this.proxy = proxy;
    -058        this.plugin = proxy.getPluginManager().getPlugin(plugin.getClass().getAnnotation(Plugin.class).id()).get();
    -059        this.formatters.put(MessageType.ERROR, defaultFormatter = new VelocityMessageFormatter(TextColor.RED, TextColor.YELLOW, TextColor.RED));
    -060        this.formatters.put(MessageType.SYNTAX, new VelocityMessageFormatter(TextColor.YELLOW, TextColor.GREEN, TextColor.WHITE));
    -061        this.formatters.put(MessageType.INFO, new VelocityMessageFormatter(TextColor.BLUE, TextColor.DARK_GREEN, TextColor.GREEN));
    -062        this.formatters.put(MessageType.HELP, new VelocityMessageFormatter(TextColor.AQUA, TextColor.GREEN, TextColor.YELLOW));
    -063        
    -064        getLocales();
    -065        
    -066        proxy.getEventManager().register(plugin, new ACFVelocityListener(this, this.plugin, proxy));
    -067        
    -068        registerDependency(plugin.getClass(), plugin);
    -069        registerDependency(Plugin.class, plugin);
    -070        registerDependency(ProxyServer.class, proxy);
    -071    }
    -072
    -073    public ProxyServer getProxy() {
    -074        return this.proxy;
    -075    }
    -076
    -077    public PluginContainer getPlugin() {
    -078        return this.plugin;
    -079    }
    -080
    -081    @Override
    -082    public synchronized CommandContexts<VelocityCommandExecutionContext> getCommandContexts() {
    -083        if (this.contexts == null) {
    -084            this.contexts = new VelocityCommandContexts(proxy, this);
    -085        }
    -086        return contexts;
    -087    }
    -088
    -089    @Override
    -090    public synchronized CommandCompletions<VelocityCommandCompletionContext> getCommandCompletions() {
    -091        if (this.completions == null) {
    -092            this.completions = new VelocityCommandCompletions(proxy, this);
    -093        }
    -094        return completions;
    -095    }
    -096
    -097    @Override
    -098    public VelocityLocales getLocales() {
    -099        if (this.locales == null) {
    -100            this.locales = new VelocityLocales(this);
    -101            this.locales.loadLanguages();
    -102        }
    -103        return locales;
    -104    }
    -105
    -106    public void readLocale(Player player) {
    -107        if (!player.isActive()) {
    -108            return;
    -109        }
    -110
    -111        //This can be null if we didn't received a settings packet
    -112        Locale locale = player.getPlayerSettings().getLocale();
    -113        if (locale != null) {
    -114            setIssuerLocale(player, player.getPlayerSettings().getLocale());
    -115        }
    -116    }
    -117
    -118    @Override
    -119    public void registerCommand(BaseCommand command) {
    -120        command.onRegister(this);
    -121        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    -122            String commandName = entry.getKey().toLowerCase();
    -123            VelocityRootCommand velocityCommand = (VelocityRootCommand) entry.getValue();
    -124            if (!velocityCommand.isRegistered) {
    -125                proxy.getCommandManager().register(velocityCommand, commandName);
    -126            }
    -127            velocityCommand.isRegistered = true;
    -128            registeredCommands.put(commandName, velocityCommand);
    -129        }
    -130    }
    -131
    -132    public void unregisterCommand(BaseCommand command) {
    -133        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    -134            String commandName = entry.getKey().toLowerCase();
    -135            VelocityRootCommand velocityCommand = (VelocityRootCommand) entry.getValue();
    -136            velocityCommand.getSubCommands().values().removeAll(command.subCommands.values());
    -137            if (velocityCommand.getSubCommands().isEmpty() && velocityCommand.isRegistered)  {
    -138                unregisterCommand(velocityCommand);
    -139                velocityCommand.isRegistered = false;
    -140                registeredCommands.remove(commandName);
    -141            }
    -142        }
    -143    }
    -144
    -145    public void unregisterCommand(VelocityRootCommand command) {
    -146        proxy.getCommandManager().unregister(command.getCommandName());
    -147    }
    -148
    -149    public void unregisterCommands() {
    -150        for (Map.Entry<String, VelocityRootCommand> entry : registeredCommands.entrySet()) {
    -151            unregisterCommand(entry.getValue());
    -152        }
    -153    }
    -154
    -155    @Override
    -156    public boolean hasRegisteredCommands() {
    -157        return !registeredCommands.isEmpty();
    -158    }
    -159
    -160    @Override
    -161    public boolean isCommandIssuer(Class<?> aClass) {
    -162        return CommandSource.class.isAssignableFrom(aClass);
    -163    }
    -164
    -165    @Override
    -166    public VelocityCommandIssuer getCommandIssuer(Object issuer) {
    -167        if (!(issuer instanceof CommandSource)) {
    -168            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
    -169        }
    -170        return new VelocityCommandIssuer(this, (CommandSource) issuer);
    -171    }
    -172
    -173    @Override
    -174    public RootCommand createRootCommand(String cmd) {
    -175        return new VelocityRootCommand(this, cmd);
    -176    }
    -177    
    -178    @Override
    -179    public Collection<RootCommand> getRegisteredRootCommands() {
    -180        return Collections.unmodifiableCollection(registeredCommands.values());
    -181    }
    -182
    -183    @Override
    -184    public VelocityCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
    -185        return new VelocityCommandExecutionContext(command, parameter, (VelocityCommandIssuer) sender, args, i, passedArgs);
    -186    }
    -187
    -188    @Override
    -189    public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
    -190        return new VelocityCommandCompletionContext(command, (VelocityCommandIssuer) sender, input, config, args);
    -191    }
    -192
    -193    @Override
    -194    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
    -195        return new RegisteredCommand(command, cmdName, method, prefSubCommand);
    -196    }
    -197
    -198    @Override
    -199    public VelocityConditionContext createConditionContext(CommandIssuer issuer, String config) {
    -200        return new VelocityConditionContext((VelocityCommandIssuer) issuer, config);
    -201    }
    -202
    -203    @Override
    -204    public void log(LogLevel level, String message, Throwable throwable) {
    -205        // TODO: Find better solution
    -206        Logger logger = LoggerFactory.getLogger(plugin.getClass());
    -207        if (level == LogLevel.INFO) {
    -208            logger.info(LogLevel.LOG_PREFIX + message);
    -209        } else {
    -210            logger.warn(LogLevel.LOG_PREFIX + message);
    -211        }
    -212        
    -213        if (throwable != null) {
    -214            for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    -215                if (level == LogLevel.INFO) {
    -216                    logger.info(LogLevel.LOG_PREFIX + line);
    -217                } else {
    -218                    logger.warn(LogLevel.LOG_PREFIX + line);
    -219                }
    -220            }
    -221        }
    -222    }
    -223
    -224
    -225    @Override
    -226    public String getCommandPrefix(CommandIssuer issuer) {
    -227        return issuer.isPlayer() ? "/" : "";
    -228    }
    -229}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import java.lang.reflect.Method;
    +027import java.util.Collection;
    +028import java.util.Collections;
    +029import java.util.HashMap;
    +030import java.util.List;
    +031import java.util.Locale;
    +032import java.util.Map;
    +033
    +034import org.slf4j.Logger;
    +035import org.slf4j.LoggerFactory;
    +036
    +037import com.velocitypowered.api.command.CommandSource;
    +038import com.velocitypowered.api.plugin.Plugin;
    +039import com.velocitypowered.api.plugin.PluginContainer;
    +040import com.velocitypowered.api.proxy.Player;
    +041import com.velocitypowered.api.proxy.ProxyServer;
    +042
    +043import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
    +044import net.kyori.text.format.TextColor;
    +045
    +046public class VelocityCommandManager extends
    +047        CommandManager<CommandSource, VelocityCommandIssuer, TextColor, VelocityMessageFormatter, VelocityCommandExecutionContext, VelocityConditionContext> {
    +048
    +049    protected final ProxyServer proxy;
    +050    protected final PluginContainer plugin;
    +051    protected Map<String, VelocityRootCommand> registeredCommands = new HashMap<>();
    +052    protected VelocityCommandContexts contexts;
    +053    protected VelocityCommandCompletions completions;
    +054    protected VelocityLocales locales;
    +055
    +056    public VelocityCommandManager(ProxyServer proxy, Object plugin) {
    +057        this.proxy = proxy;
    +058        this.plugin = proxy.getPluginManager().getPlugin(plugin.getClass().getAnnotation(Plugin.class).id()).get();
    +059        this.formatters.put(MessageType.ERROR, defaultFormatter = new VelocityMessageFormatter(TextColor.RED, TextColor.YELLOW, TextColor.RED));
    +060        this.formatters.put(MessageType.SYNTAX, new VelocityMessageFormatter(TextColor.YELLOW, TextColor.GREEN, TextColor.WHITE));
    +061        this.formatters.put(MessageType.INFO, new VelocityMessageFormatter(TextColor.BLUE, TextColor.DARK_GREEN, TextColor.GREEN));
    +062        this.formatters.put(MessageType.HELP, new VelocityMessageFormatter(TextColor.AQUA, TextColor.GREEN, TextColor.YELLOW));
    +063        
    +064        getLocales();
    +065        
    +066        proxy.getEventManager().register(plugin, new ACFVelocityListener(this, this.plugin, proxy));
    +067        
    +068        registerDependency(plugin.getClass(), plugin);
    +069        registerDependency(Plugin.class, plugin);
    +070        registerDependency(ProxyServer.class, proxy);
    +071    }
    +072
    +073    public ProxyServer getProxy() {
    +074        return this.proxy;
    +075    }
    +076
    +077    public PluginContainer getPlugin() {
    +078        return this.plugin;
    +079    }
    +080
    +081    @Override
    +082    public synchronized CommandContexts<VelocityCommandExecutionContext> getCommandContexts() {
    +083        if (this.contexts == null) {
    +084            this.contexts = new VelocityCommandContexts(proxy, this);
    +085        }
    +086        return contexts;
    +087    }
    +088
    +089    @Override
    +090    public synchronized CommandCompletions<VelocityCommandCompletionContext> getCommandCompletions() {
    +091        if (this.completions == null) {
    +092            this.completions = new VelocityCommandCompletions(proxy, this);
    +093        }
    +094        return completions;
    +095    }
    +096
    +097    @Override
    +098    public VelocityLocales getLocales() {
    +099        if (this.locales == null) {
    +100            this.locales = new VelocityLocales(this);
    +101            this.locales.loadLanguages();
    +102        }
    +103        return locales;
    +104    }
    +105
    +106    public void readLocale(Player player) {
    +107        if (!player.isActive()) {
    +108            return;
    +109        }
    +110
    +111        //This can be null if we didn't received a settings packet
    +112        Locale locale = player.getPlayerSettings().getLocale();
    +113        if (locale != null) {
    +114            setIssuerLocale(player, player.getPlayerSettings().getLocale());
    +115        }
    +116    }
    +117
    +118    @Override
    +119    public void registerCommand(BaseCommand command) {
    +120        command.onRegister(this);
    +121        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    +122            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
    +123            VelocityRootCommand velocityCommand = (VelocityRootCommand) entry.getValue();
    +124            if (!velocityCommand.isRegistered) {
    +125                proxy.getCommandManager().register(velocityCommand, commandName);
    +126            }
    +127            velocityCommand.isRegistered = true;
    +128            registeredCommands.put(commandName, velocityCommand);
    +129        }
    +130    }
    +131
    +132    public void unregisterCommand(BaseCommand command) {
    +133        for (Map.Entry<String, RootCommand> entry : command.registeredCommands.entrySet()) {
    +134            String commandName = entry.getKey().toLowerCase(Locale.ENGLISH);
    +135            VelocityRootCommand velocityCommand = (VelocityRootCommand) entry.getValue();
    +136            velocityCommand.getSubCommands().values().removeAll(command.subCommands.values());
    +137            if (velocityCommand.getSubCommands().isEmpty() && velocityCommand.isRegistered)  {
    +138                unregisterCommand(velocityCommand);
    +139                velocityCommand.isRegistered = false;
    +140                registeredCommands.remove(commandName);
    +141            }
    +142        }
    +143    }
    +144
    +145    public void unregisterCommand(VelocityRootCommand command) {
    +146        proxy.getCommandManager().unregister(command.getCommandName());
    +147    }
    +148
    +149    public void unregisterCommands() {
    +150        for (Map.Entry<String, VelocityRootCommand> entry : registeredCommands.entrySet()) {
    +151            unregisterCommand(entry.getValue());
    +152        }
    +153    }
    +154
    +155    @Override
    +156    public boolean hasRegisteredCommands() {
    +157        return !registeredCommands.isEmpty();
    +158    }
    +159
    +160    @Override
    +161    public boolean isCommandIssuer(Class<?> aClass) {
    +162        return CommandSource.class.isAssignableFrom(aClass);
    +163    }
    +164
    +165    @Override
    +166    public VelocityCommandIssuer getCommandIssuer(Object issuer) {
    +167        if (!(issuer instanceof CommandSource)) {
    +168            throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer.");
    +169        }
    +170        return new VelocityCommandIssuer(this, (CommandSource) issuer);
    +171    }
    +172
    +173    @Override
    +174    public RootCommand createRootCommand(String cmd) {
    +175        return new VelocityRootCommand(this, cmd);
    +176    }
    +177    
    +178    @Override
    +179    public Collection<RootCommand> getRegisteredRootCommands() {
    +180        return Collections.unmodifiableCollection(registeredCommands.values());
    +181    }
    +182
    +183    @Override
    +184    public VelocityCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List<String> args, int i, Map<String, Object> passedArgs) {
    +185        return new VelocityCommandExecutionContext(command, parameter, (VelocityCommandIssuer) sender, args, i, passedArgs);
    +186    }
    +187
    +188    @Override
    +189    public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) {
    +190        return new VelocityCommandCompletionContext(command, (VelocityCommandIssuer) sender, input, config, args);
    +191    }
    +192
    +193    @Override
    +194    public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
    +195        return new RegisteredCommand(command, cmdName, method, prefSubCommand);
    +196    }
    +197
    +198    @Override
    +199    public VelocityConditionContext createConditionContext(CommandIssuer issuer, String config) {
    +200        return new VelocityConditionContext((VelocityCommandIssuer) issuer, config);
    +201    }
    +202
    +203    @Override
    +204    public void log(LogLevel level, String message, Throwable throwable) {
    +205        // TODO: Find better solution
    +206        Logger logger = LoggerFactory.getLogger(plugin.getClass());
    +207        if (level == LogLevel.INFO) {
    +208            logger.info(LogLevel.LOG_PREFIX + message);
    +209        } else {
    +210            logger.warn(LogLevel.LOG_PREFIX + message);
    +211        }
    +212        
    +213        if (throwable != null) {
    +214            for (String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
    +215                if (level == LogLevel.INFO) {
    +216                    logger.info(LogLevel.LOG_PREFIX + line);
    +217                } else {
    +218                    logger.warn(LogLevel.LOG_PREFIX + line);
    +219                }
    +220            }
    +221        }
    +222    }
    +223
    +224
    +225    @Override
    +226    public String getCommandPrefix(CommandIssuer issuer) {
    +227        return issuer.isPlayer() ? "/" : "";
    +228    }
    +229}
     
     
     
    @@ -297,5 +298,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityConditionContext.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityConditionContext.html index 8ec97b2b..486b588d 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityConditionContext.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityConditionContext.html @@ -1,30 +1,31 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import com.velocitypowered.api.command.CommandSource;
    -004import com.velocitypowered.api.proxy.Player;
    -005
    -006public class VelocityConditionContext extends ConditionContext <VelocityCommandIssuer> {
    -007    VelocityConditionContext(VelocityCommandIssuer issuer, String config) {
    -008        super(issuer, config);
    -009    }
    -010
    -011
    -012    public CommandSource getSender() {
    -013        return getIssuer().getIssuer();
    -014    }
    -015
    -016    public Player getPlayer() {
    -017        return getIssuer().getPlayer();
    -018    }
    -019}
    +
    001package co.aikar.commands;
    +002
    +003import com.velocitypowered.api.command.CommandSource;
    +004import com.velocitypowered.api.proxy.Player;
    +005
    +006public class VelocityConditionContext extends ConditionContext <VelocityCommandIssuer> {
    +007    VelocityConditionContext(VelocityCommandIssuer issuer, String config) {
    +008        super(issuer, config);
    +009    }
    +010
    +011
    +012    public CommandSource getSender() {
    +013        return getIssuer().getIssuer();
    +014    }
    +015
    +016    public Player getPlayer() {
    +017        return getIssuer().getPlayer();
    +018    }
    +019}
     
     
     
    @@ -87,5 +88,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityLocales.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityLocales.html index af96d739..979f08e6 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityLocales.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityLocales.html @@ -1,30 +1,33 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003public class VelocityLocales extends Locales {
    -004    private final VelocityCommandManager manager;
    -005
    -006    public VelocityLocales(VelocityCommandManager manager) {
    -007        super(manager);
    -008
    -009        this.manager = manager;
    -010        this.addBundleClassLoader(this.manager.getPlugin().getClass().getClassLoader());
    -011    }
    -012
    -013    @Override
    -014    public void loadLanguages() {
    -015        super.loadLanguages();
    -016        String pluginName = "acf-" + manager.plugin.getDescription().getName().get();
    -017        addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase());
    -018    }
    -019}
    +
    001package co.aikar.commands;
    +002
    +003import java.util.Locale;
    +004
    +005public class VelocityLocales extends Locales {
    +006    private final VelocityCommandManager manager;
    +007
    +008    public VelocityLocales(VelocityCommandManager manager) {
    +009        super(manager);
    +010
    +011        this.manager = manager;
    +012        this.addBundleClassLoader(this.manager.getPlugin().getClass().getClassLoader());
    +013    }
    +014
    +015    @Override
    +016    public void loadLanguages() {
    +017        super.loadLanguages();
    +018        String pluginName = "acf-" + manager.plugin.getDescription().getName().get();
    +019        addMessageBundles("acf-minecraft", pluginName, pluginName.toLowerCase(Locale.ENGLISH));
    +020    }
    +021}
     
     
     
    @@ -87,5 +90,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityMessageFormatter.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityMessageFormatter.html index 071a4752..40604f15 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityMessageFormatter.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityMessageFormatter.html @@ -1,28 +1,29 @@ - + Source code +
    -
    001package co.aikar.commands;
    -002
    -003import net.kyori.text.format.TextColor;
    -004import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
    -005
    -006public class VelocityMessageFormatter extends MessageFormatter<TextColor> {
    -007
    -008    public VelocityMessageFormatter(TextColor... colors) {
    -009        super(colors);
    -010    }
    -011
    -012    @Override
    -013    @SuppressWarnings("deprecation")
    -014    String format(TextColor color, String message) {
    -015        return LegacyComponentSerializer.legacy().serialize(LegacyComponentSerializer.legacy().deserialize(message).color(color));
    -016    }
    -017}
    +
    001package co.aikar.commands;
    +002
    +003import net.kyori.text.format.TextColor;
    +004import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
    +005
    +006public class VelocityMessageFormatter extends MessageFormatter<TextColor> {
    +007
    +008    public VelocityMessageFormatter(TextColor... colors) {
    +009        super(colors);
    +010    }
    +011
    +012    @Override
    +013    @SuppressWarnings("deprecation")
    +014    String format(TextColor color, String message) {
    +015        return LegacyComponentSerializer.legacy().serialize(LegacyComponentSerializer.legacy().deserialize(message).color(color));
    +016    }
    +017}
     
     
     
    @@ -85,5 +86,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/VelocityRootCommand.html b/docs/acf-velocity/src-html/co/aikar/commands/VelocityRootCommand.html index e81a9ff2..1add73e7 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/VelocityRootCommand.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/VelocityRootCommand.html @@ -1,102 +1,103 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands;
    -025
    -026import java.util.ArrayList;
    -027import java.util.List;
    -028
    -029import com.google.common.collect.HashMultimap;
    -030import com.google.common.collect.SetMultimap;
    -031import com.velocitypowered.api.command.Command;
    -032import com.velocitypowered.api.command.CommandSource;
    -033
    -034public class VelocityRootCommand implements Command, RootCommand {
    -035
    -036    private final VelocityCommandManager manager;
    -037    private final String name;
    -038    private BaseCommand defCommand;
    -039    private SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
    -040    private List<BaseCommand> children = new ArrayList<>();
    -041    boolean isRegistered = false;
    -042
    -043    VelocityRootCommand(VelocityCommandManager manager, String name) {
    -044        this.manager = manager;
    -045        this.name = name;
    -046    }
    -047
    -048    @Override
    -049    public String getCommandName() {
    -050        return name;
    -051    }
    -052
    -053    @Override
    -054    public void addChild(BaseCommand command) {
    -055        if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) {
    -056            this.defCommand = command;
    -057
    -058        }
    -059        this.addChildShared(this.children, this.subCommands, command);
    -060    }
    -061
    -062    @Override
    -063    public CommandManager getManager() {
    -064        return manager;
    -065    }
    -066
    -067    @Override
    -068    public SetMultimap<String, RegisteredCommand> getSubCommands() {
    -069        return subCommands;
    -070    }
    -071
    -072    @Override
    -073    public List<BaseCommand> getChildren() {
    -074        return children;
    -075    }
    -076
    -077    @Override
    -078    public void execute(CommandSource source, String[] args) {
    -079        execute(manager.getCommandIssuer(source), getCommandName(), args);
    -080    }
    -081
    -082    @Override
    -083    public List<String> suggest(CommandSource source, String[] args) {
    -084        return getTabCompletions(manager.getCommandIssuer(source), getCommandName(), args);
    -085    }
    -086
    -087    @Override
    -088    public BaseCommand getDefCommand() {
    -089        return defCommand;
    -090    }
    -091}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands;
    +025
    +026import java.util.ArrayList;
    +027import java.util.List;
    +028
    +029import com.google.common.collect.HashMultimap;
    +030import com.google.common.collect.SetMultimap;
    +031import com.velocitypowered.api.command.Command;
    +032import com.velocitypowered.api.command.CommandSource;
    +033
    +034public class VelocityRootCommand implements Command, RootCommand {
    +035
    +036    private final VelocityCommandManager manager;
    +037    private final String name;
    +038    private BaseCommand defCommand;
    +039    private SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create();
    +040    private List<BaseCommand> children = new ArrayList<>();
    +041    boolean isRegistered = false;
    +042
    +043    VelocityRootCommand(VelocityCommandManager manager, String name) {
    +044        this.manager = manager;
    +045        this.name = name;
    +046    }
    +047
    +048    @Override
    +049    public String getCommandName() {
    +050        return name;
    +051    }
    +052
    +053    @Override
    +054    public void addChild(BaseCommand command) {
    +055        if (this.defCommand == null || !command.subCommands.get(BaseCommand.DEFAULT).isEmpty()) {
    +056            this.defCommand = command;
    +057
    +058        }
    +059        this.addChildShared(this.children, this.subCommands, command);
    +060    }
    +061
    +062    @Override
    +063    public CommandManager getManager() {
    +064        return manager;
    +065    }
    +066
    +067    @Override
    +068    public SetMultimap<String, RegisteredCommand> getSubCommands() {
    +069        return subCommands;
    +070    }
    +071
    +072    @Override
    +073    public List<BaseCommand> getChildren() {
    +074        return children;
    +075    }
    +076
    +077    @Override
    +078    public void execute(CommandSource source, String[] args) {
    +079        execute(manager.getCommandIssuer(source), getCommandName(), args);
    +080    }
    +081
    +082    @Override
    +083    public List<String> suggest(CommandSource source, String[] args) {
    +084        return getTabCompletions(manager.getCommandIssuer(source), getCommandName(), args);
    +085    }
    +086
    +087    @Override
    +088    public BaseCommand getDefCommand() {
    +089        return defCommand;
    +090    }
    +091}
     
     
     
    @@ -159,5 +160,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/contexts/OnlinePlayer.html b/docs/acf-velocity/src-html/co/aikar/commands/contexts/OnlinePlayer.html index b4b2a41f..ceebe466 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/contexts/OnlinePlayer.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/contexts/OnlinePlayer.html @@ -1,47 +1,48 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands.contexts;
    -025
    -026import com.velocitypowered.api.proxy.Player;
    -027
    -028/**
    -029 * @deprecated Use {@link co.aikar.commands.velocity.contexts.OnlinePlayer instead}
    -030 */
    -031@Deprecated
    -032public class OnlinePlayer extends co.aikar.commands.velocity.contexts.OnlinePlayer {
    -033    public OnlinePlayer(Player player) {
    -034        super(player);
    -035    }
    -036}
    +
    001/*
    +002 * Copyright (c) 2016-2019 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands.contexts;
    +025
    +026import com.velocitypowered.api.proxy.Player;
    +027
    +028/**
    +029 * @deprecated Use {@link co.aikar.commands.velocity.contexts.OnlinePlayer instead}
    +030 */
    +031@Deprecated
    +032public class OnlinePlayer extends co.aikar.commands.velocity.contexts.OnlinePlayer {
    +033    public OnlinePlayer(Player player) {
    +034        super(player);
    +035    }
    +036}
     
     
     
    @@ -104,5 +105,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/src-html/co/aikar/commands/velocity/contexts/OnlinePlayer.html b/docs/acf-velocity/src-html/co/aikar/commands/velocity/contexts/OnlinePlayer.html index 17c4b479..15d4b9f6 100644 --- a/docs/acf-velocity/src-html/co/aikar/commands/velocity/contexts/OnlinePlayer.html +++ b/docs/acf-velocity/src-html/co/aikar/commands/velocity/contexts/OnlinePlayer.html @@ -1,70 +1,71 @@ - + Source code +
    -
    001/*
    -002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    -003 *
    -004 *  Permission is hereby granted, free of charge, to any person obtaining
    -005 *  a copy of this software and associated documentation files (the
    -006 *  "Software"), to deal in the Software without restriction, including
    -007 *  without limitation the rights to use, copy, modify, merge, publish,
    -008 *  distribute, sublicense, and/or sell copies of the Software, and to
    -009 *  permit persons to whom the Software is furnished to do so, subject to
    -010 *  the following conditions:
    -011 *
    -012 *  The above copyright notice and this permission notice shall be
    -013 *  included in all copies or substantial portions of the Software.
    -014 *
    -015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    -016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    -017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    -018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    -019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    -020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    -021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    -022 */
    -023
    -024package co.aikar.commands.velocity.contexts;
    -025
    -026import java.util.Objects;
    -027
    -028import com.velocitypowered.api.proxy.Player;
    -029
    -030public class OnlinePlayer {
    -031
    -032    public final Player player;
    -033
    -034    public OnlinePlayer(Player player) {
    -035        this.player = player;
    -036    }
    -037
    -038    public Player getPlayer() {
    -039        return player;
    -040    }
    -041
    -042    @Override
    -043    public boolean equals(Object o) {
    -044        if (this == o) return true;
    -045        if (o == null || getClass() != o.getClass()) return false;
    -046        OnlinePlayer that = (OnlinePlayer) o;
    -047        return Objects.equals(player, that.player);
    -048    }
    -049
    -050    @Override
    -051    public int hashCode() {
    -052        return Objects.hash(player);
    -053    }
    -054
    -055    @Override
    -056    public String toString() {
    -057        return "OnlinePlayer{player=" + player + '}';
    -058    }
    -059}
    +
    001/*
    +002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
    +003 *
    +004 *  Permission is hereby granted, free of charge, to any person obtaining
    +005 *  a copy of this software and associated documentation files (the
    +006 *  "Software"), to deal in the Software without restriction, including
    +007 *  without limitation the rights to use, copy, modify, merge, publish,
    +008 *  distribute, sublicense, and/or sell copies of the Software, and to
    +009 *  permit persons to whom the Software is furnished to do so, subject to
    +010 *  the following conditions:
    +011 *
    +012 *  The above copyright notice and this permission notice shall be
    +013 *  included in all copies or substantial portions of the Software.
    +014 *
    +015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    +016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    +017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    +018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    +019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    +020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    +021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +022 */
    +023
    +024package co.aikar.commands.velocity.contexts;
    +025
    +026import java.util.Objects;
    +027
    +028import com.velocitypowered.api.proxy.Player;
    +029
    +030public class OnlinePlayer {
    +031
    +032    public final Player player;
    +033
    +034    public OnlinePlayer(Player player) {
    +035        this.player = player;
    +036    }
    +037
    +038    public Player getPlayer() {
    +039        return player;
    +040    }
    +041
    +042    @Override
    +043    public boolean equals(Object o) {
    +044        if (this == o) return true;
    +045        if (o == null || getClass() != o.getClass()) return false;
    +046        OnlinePlayer that = (OnlinePlayer) o;
    +047        return Objects.equals(player, that.player);
    +048    }
    +049
    +050    @Override
    +051    public int hashCode() {
    +052        return Objects.hash(player);
    +053    }
    +054
    +055    @Override
    +056    public String toString() {
    +057        return "OnlinePlayer{player=" + player + '}';
    +058    }
    +059}
     
     
     
    @@ -127,5 +128,6 @@
     
     
    +
    diff --git a/docs/acf-velocity/stylesheet.css b/docs/acf-velocity/stylesheet.css index 98055b22..fa246765 100644 --- a/docs/acf-velocity/stylesheet.css +++ b/docs/acf-velocity/stylesheet.css @@ -1,35 +1,51 @@ -/* Javadoc style sheet */ -/* -Overall document style -*/ +/* + * Javadoc style sheet + */ @import url('resources/fonts/dejavu.css'); +/* + * Styles for individual HTML elements. + * + * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular + * HTML element throughout the page. + */ + body { background-color:#ffffff; color:#353833; font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; font-size:14px; margin:0; + padding:0; + height:100%; + width:100%; +} +iframe { + margin:0; + padding:0; + height:100%; + width:100%; + overflow-y:scroll; + border:none; } a:link, a:visited { text-decoration:none; color:#4A6782; } -a:hover, a:focus { +a[href]:hover, a[href]:focus { text-decoration:none; color:#bb7a2a; } -a:active { - text-decoration:none; - color:#4A6782; -} a[name] { color:#353833; } -a[name]:hover { - text-decoration:none; - color:#353833; +a[name]:before, a[name]:target, a[id]:before, a[id]:target { + content:""; + display:inline-block; + position:relative; + padding-top:129px; + margin-top:-129px; } pre { font-family:'DejaVu Sans Mono', monospace; @@ -78,9 +94,16 @@ table tr td dt code { sup { font-size:8px; } + /* -Document title and Copyright styles -*/ + * Styles for HTML generated by javadoc. + * + * These are style classes that are used by the standard doclet to generate HTML documentation. + */ + +/* + * Styles for document title and copyright. + */ .clear { clear:both; height:0px; @@ -111,8 +134,8 @@ Document title and Copyright styles font-weight:bold; } /* -Navigation bar styles -*/ + * Styles for navigation bar. + */ .bar { background-color:#4D7A97; color:#FFFFFF; @@ -121,6 +144,15 @@ Navigation bar styles font-size:11px; margin:0; } +.navPadding { + padding-top: 107px; +} +.fixedNav { + position:fixed; + width:100%; + z-index:999; + background-color:#ffffff; +} .topNav { background-color:#4D7A97; color:#FFFFFF; @@ -170,7 +202,22 @@ ul.navList li{ padding: 5px 6px; text-transform:uppercase; } -ul.subNavList li{ +ul.navListSearch { + float:right; + margin:0 0 0 0; + padding:0; +} +ul.navListSearch li { + list-style:none; + float:right; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch li label { + position:relative; + right:-16px; +} +ul.subNavList li { list-style:none; float:left; } @@ -196,21 +243,29 @@ ul.subNavList li{ overflow:hidden; } /* -Page header and footer styles -*/ + * Styles for page header and footer. + */ .header, .footer { clear:both; margin:0 20px; padding:5px 0 0 0; } -.indexHeader { - margin:10px; +.indexNav { position:relative; + font-size:12px; + background-color:#dee3e9; } -.indexHeader span{ - margin-right:15px; +.indexNav ul { + margin-top:0; + padding:5px; } -.indexHeader h1 { +.indexNav ul li { + display:inline; + list-style-type:none; + padding-right:10px; + text-transform:uppercase; +} +.indexNav h1 { font-size:13px; } .title { @@ -232,8 +287,8 @@ Page header and footer styles font-size:13px; } /* -Heading styles -*/ + * Styles for headings. + */ div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { background-color:#dee3e9; border:1px solid #d0d9e0; @@ -254,9 +309,10 @@ ul.blockList li.blockList h2 { padding:0px 0 20px 0; } /* -Page layout container styles -*/ -.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + * Styles for page layout containers. + */ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer, +.allClassesContainer, .allPackagesContainer { clear:both; padding:10px 20px; position:relative; @@ -287,7 +343,7 @@ Page layout container styles .contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { margin:5px 0 10px 0px; font-size:14px; - font-family:'DejaVu Sans Mono',monospace; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } .serializedFormContainer dl.nameValue dt { margin-left:1px; @@ -301,8 +357,11 @@ Page layout container styles display:inline; } /* -List styles -*/ + * Styles for lists. + */ +li.circle { + list-style:circle; +} ul.horizontal li { display:inline; font-size:0.9em; @@ -355,19 +414,22 @@ table tr td dl, table tr td dl dt, table tr td dl dd { margin-bottom:1px; } /* -Table styles -*/ -.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + * Styles for tables. + */ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary, +.requiresSummary, .packagesSummary, .providesSummary, .usesSummary { width:100%; + border-spacing:0; border-left:1px solid #EEE; border-right:1px solid #EEE; border-bottom:1px solid #EEE; } -.overviewSummary, .memberSummary { +.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary { padding:0px; } .overviewSummary caption, .memberSummary caption, .typeSummary caption, -.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption, +.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption { position:relative; text-align:left; background-repeat:no-repeat; @@ -382,17 +444,31 @@ Table styles white-space:pre; } .overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, -.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.constantsSummary caption a:link, .deprecatedSummary caption a:link, +.requiresSummary caption a:link, .packagesSummary caption a:link, .providesSummary caption a:link, +.usesSummary caption a:link, .overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, -.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.requiresSummary caption a:hover, .packagesSummary caption a:hover, .providesSummary caption a:hover, +.usesSummary caption a:hover, .overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, -.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.constantsSummary caption a:active, .deprecatedSummary caption a:active, +.requiresSummary caption a:active, .packagesSummary caption a:active, .providesSummary caption a:active, +.usesSummary caption a:active, .overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, -.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { +.constantsSummary caption a:visited, .deprecatedSummary caption a:visited, +.requiresSummary caption a:visited, .packagesSummary caption a:visited, .providesSummary caption a:visited, +.usesSummary caption a:visited { color:#FFFFFF; } +.useSummary caption a:link, .useSummary caption a:hover, .useSummary caption a:active, +.useSummary caption a:visited { + color:#1f389c; +} .overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, -.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span, +.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span, +.usesSummary caption span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -404,7 +480,8 @@ Table styles border: none; height:16px; } -.memberSummary caption span.activeTableTab span { +.memberSummary caption span.activeTableTab span, .packagesSummary caption span.activeTableTab span, +.overviewSummary caption span.activeTableTab span, .typeSummary caption span.activeTableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -415,7 +492,8 @@ Table styles background-color:#F8981D; height:16px; } -.memberSummary caption span.tableTab span { +.memberSummary caption span.tableTab span, .packagesSummary caption span.tableTab span, +.overviewSummary caption span.tableTab span, .typeSummary caption span.tableTab span { white-space:nowrap; padding-top:5px; padding-left:12px; @@ -426,7 +504,10 @@ Table styles background-color:#4D7A97; height:16px; } -.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab, +.packagesSummary caption span.tableTab, .packagesSummary caption span.activeTableTab, +.overviewSummary caption span.tableTab, .overviewSummary caption span.activeTableTab, +.typeSummary caption span.tableTab, .typeSummary caption span.activeTableTab { padding-top:0px; padding-left:0px; padding-right:0px; @@ -435,14 +516,16 @@ Table styles display:inline; } .overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, -.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd, +.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd { display:none; width:5px; position:relative; float:left; background-color:#F8981D; } -.memberSummary .activeTableTab .tabEnd { +.memberSummary .activeTableTab .tabEnd, .packagesSummary .activeTableTab .tabEnd, +.overviewSummary .activeTableTab .tabEnd, .typeSummary .activeTableTab .tabEnd { display:none; width:5px; margin-right:3px; @@ -450,66 +533,88 @@ Table styles float:left; background-color:#F8981D; } -.memberSummary .tableTab .tabEnd { +.memberSummary .tableTab .tabEnd, .packagesSummary .tableTab .tabEnd, +.overviewSummary .tableTab .tabEnd, .typeSummary .tableTab .tabEnd { display:none; width:5px; margin-right:3px; position:relative; background-color:#4D7A97; float:left; - +} +.rowColor th, .altColor th { + font-weight:normal; } .overviewSummary td, .memberSummary td, .typeSummary td, -.useSummary td, .constantsSummary td, .deprecatedSummary td { +.useSummary td, .constantsSummary td, .deprecatedSummary td, +.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td { text-align:left; padding:0px 0px 12px 10px; } -th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, -td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .useSummary th, +.constantsSummary th, .packagesSummary th, td.colFirst, td.colSecond, td.colLast, .useSummary td, +.constantsSummary td { vertical-align:top; padding-right:0px; padding-top:8px; padding-bottom:3px; } -th.colFirst, th.colLast, th.colOne, .constantsSummary th { +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .constantsSummary th, +.packagesSummary th { background:#dee3e9; text-align:left; padding:8px 3px 3px 7px; } td.colFirst, th.colFirst { - white-space:nowrap; font-size:13px; } -td.colLast, th.colLast { +td.colSecond, th.colSecond, td.colLast, th.colConstructorName, th.colDeprecatedItemName, th.colLast { font-size:13px; } -td.colOne, th.colOne { +.constantsSummary th, .packagesSummary th { + font-size:13px; +} +.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst, +.providesSummary td.colLast { + white-space:normal; font-size:13px; } .overviewSummary td.colFirst, .overviewSummary th.colFirst, -.useSummary td.colFirst, .useSummary th.colFirst, -.overviewSummary td.colOne, .overviewSummary th.colOne, +.requiresSummary td.colFirst, .requiresSummary th.colFirst, +.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th, +.usesSummary td.colFirst, .usesSummary th.colFirst, +.providesSummary td.colFirst, .providesSummary th.colFirst, .memberSummary td.colFirst, .memberSummary th.colFirst, -.memberSummary td.colOne, .memberSummary th.colOne, -.typeSummary td.colFirst{ - width:25%; +.memberSummary td.colSecond, .memberSummary th.colSecond, .memberSummary th.colConstructorName, +.typeSummary td.colFirst, .typeSummary th.colFirst { vertical-align:top; } -td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { +.packagesSummary th.colLast, .packagesSummary td.colLast { + white-space:normal; +} +td.colFirst a:link, td.colFirst a:visited, +td.colSecond a:link, td.colSecond a:visited, +th.colFirst a:link, th.colFirst a:visited, +th.colSecond a:link, th.colSecond a:visited, +th.colConstructorName a:link, th.colConstructorName a:visited, +th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited, +.constantValuesContainer td a:link, .constantValuesContainer td a:visited, +.allClassesContainer td a:link, .allClassesContainer td a:visited, +.allPackagesContainer td a:link, .allPackagesContainer td a:visited { font-weight:bold; } .tableSubHeadingColor { background-color:#EEEEFF; } -.altColor { +.altColor, .altColor th { background-color:#FFFFFF; } -.rowColor { +.rowColor, .rowColor th { background-color:#EEEEEF; } /* -Content styles -*/ + * Styles for contents. + */ .description pre { margin-top:0; } @@ -520,27 +625,22 @@ Content styles .docSummary { padding:0; } - ul.blockList ul.blockList ul.blockList li.blockList h3 { font-style:normal; } - div.block { font-size:14px; font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; } - td.colLast div { padding-top:0px; } - - td.colLast a { padding-bottom:3px; } /* -Formatting effect styles -*/ + * Styles for formatting effect. + */ .sourceLineNo { color:green; padding:0 30px 0 0; @@ -555,20 +655,252 @@ h1.hidden { margin:3px 10px 2px 0px; color:#474747; } -.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { +.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink, +.moduleLabelInPackage, .moduleLabelInType, .overrideSpecifyLabel, .packageLabelInType, +.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, +.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { font-weight:bold; } .deprecationComment, .emphasizedPhrase, .interfaceName { font-style:italic; } - -div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +.deprecationBlock { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +div.block div.deprecationComment, div.block div.block span.emphasizedPhrase, div.block div.block span.interfaceName { font-style:normal; } - -div.contentContainer ul.blockList li.blockList h2{ +div.contentContainer ul.blockList li.blockList h2 { padding-bottom:0px; } +/* + * Styles for IFRAME. + */ +.mainContainer { + margin:0 auto; + padding:0; + height:100%; + width:100%; + position:fixed; + top:0; + left:0; +} +.leftContainer { + height:100%; + position:fixed; + width:320px; +} +.leftTop { + position:relative; + float:left; + width:315px; + top:0; + left:0; + height:30%; + border-right:6px solid #ccc; + border-bottom:6px solid #ccc; +} +.leftBottom { + position:relative; + float:left; + width:315px; + bottom:0; + left:0; + height:70%; + border-right:6px solid #ccc; + border-top:1px solid #000; +} +.rightContainer { + position:absolute; + left:320px; + top:0; + bottom:0; + height:100%; + right:0; + border-left:1px solid #000; +} +.rightIframe { + margin:0; + padding:0; + height:100%; + right:30px; + width:100%; + overflow:visible; + margin-bottom:30px; +} +/* + * Styles specific to HTML5 elements. + */ +main, nav, header, footer, section { + display:block; +} +/* + * Styles for javadoc search. + */ +.ui-autocomplete-category { + font-weight:bold; + font-size:15px; + padding:7px 0 7px 3px; + background-color:#4D7A97; + color:#FFFFFF; +} +.resultItem { + font-size:13px; +} +.ui-autocomplete { + max-height:85%; + max-width:65%; + overflow-y:scroll; + overflow-x:scroll; + white-space:nowrap; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); +} +ul.ui-autocomplete { + position:fixed; + z-index:999999; +} +ul.ui-autocomplete li { + float:left; + clear:both; + width:100%; +} +.resultHighlight { + font-weight:bold; +} +#search { + background-image:url('resources/glass.png'); + background-size:13px; + background-repeat:no-repeat; + background-position:2px 3px; + padding-left:20px; + position:relative; + right:-18px; +} +#reset { + background-color: rgb(255,255,255); + background-image:url('resources/x.png'); + background-position:center; + background-repeat:no-repeat; + background-size:12px; + border:0 none; + width:16px; + height:17px; + position:relative; + left:-4px; + top:-4px; + font-size:0px; +} +.watermark { + color:#545454; +} +.searchTagDescResult { + font-style:italic; + font-size:11px; +} +.searchTagHolderResult { + font-style:italic; + font-size:12px; +} +.searchTagResult:before, .searchTagResult:target { + color:red; +} +.moduleGraph span { + display:none; + position:absolute; +} +.moduleGraph:hover span { + display:block; + margin: -100px 0 0 100px; + z-index: 1; +} +.methodSignature { + white-space:normal; +} + +/* + * Styles for user-provided tables. + * + * borderless: + * No borders, vertical margins, styled caption. + * This style is provided for use with existing doc comments. + * In general, borderless tables should not be used for layout purposes. + * + * plain: + * Plain borders around table and cells, vertical margins, styled caption. + * Best for small tables or for complex tables for tables with cells that span + * rows and columns, when the "striped" style does not work well. + * + * striped: + * Borders around the table and vertical borders between cells, striped rows, + * vertical margins, styled caption. + * Best for tables that have a header row, and a body containing a series of simple rows. + */ + +table.borderless, +table.plain, +table.striped { + margin-top: 10px; + margin-bottom: 10px; +} +table.borderless > caption, +table.plain > caption, +table.striped > caption { + font-weight: bold; + font-size: smaller; +} +table.borderless th, table.borderless td, +table.plain th, table.plain td, +table.striped th, table.striped td { + padding: 2px 5px; +} +table.borderless, +table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, +table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { + border: none; +} +table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { + background-color: transparent; +} +table.plain { + border-collapse: collapse; + border: 1px solid black; +} +table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { + background-color: transparent; +} +table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, +table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { + border: 1px solid black; +} +table.striped { + border-collapse: collapse; + border: 1px solid black; +} +table.striped > thead { + background-color: #E3E3E3; +} +table.striped > thead > tr > th, table.striped > thead > tr > td { + border: 1px solid black; +} +table.striped > tbody > tr:nth-child(even) { + background-color: #EEE +} +table.striped > tbody > tr:nth-child(odd) { + background-color: #FFF +} +table.striped > tbody > tr > th, table.striped > tbody > tr > td { + border-left: 1px solid black; + border-right: 1px solid black; +} +table.striped > tbody > tr > th { + font-weight: normal; +} diff --git a/docs/acf-velocity/type-search-index.js b/docs/acf-velocity/type-search-index.js new file mode 100644 index 00000000..4423e3fb --- /dev/null +++ b/docs/acf-velocity/type-search-index.js @@ -0,0 +1 @@ +typeSearchIndex = [{"p":"co.aikar.commands","l":"ACFVelocityListener"},{"p":"co.aikar.commands","l":"ACFVelocityUtil"},{"l":"All Classes","url":"allclasses-index.html"},{"p":"co.aikar.commands","l":"MinecraftMessageKeys"},{"p":"co.aikar.commands.contexts","l":"OnlinePlayer"},{"p":"co.aikar.commands.velocity.contexts","l":"OnlinePlayer"},{"p":"co.aikar.commands","l":"VelocityCommandCompletionContext"},{"p":"co.aikar.commands","l":"VelocityCommandCompletions"},{"p":"co.aikar.commands","l":"VelocityCommandContexts"},{"p":"co.aikar.commands","l":"VelocityCommandExecutionContext"},{"p":"co.aikar.commands","l":"VelocityCommandIssuer"},{"p":"co.aikar.commands","l":"VelocityCommandManager"},{"p":"co.aikar.commands","l":"VelocityConditionContext"},{"p":"co.aikar.commands","l":"VelocityLocales"},{"p":"co.aikar.commands","l":"VelocityMessageFormatter"},{"p":"co.aikar.commands","l":"VelocityRootCommand"}] \ No newline at end of file diff --git a/docs/acf-velocity/type-search-index.zip b/docs/acf-velocity/type-search-index.zip new file mode 100644 index 00000000..5dcd613c Binary files /dev/null and b/docs/acf-velocity/type-search-index.zip differ