├── .devcontainer ├── devcontainer.json ├── direnv.toml ├── docker-compose.yml └── library-scripts │ ├── common-debian.sh │ └── docker-debian.sh ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── Earthfile ├── README.md ├── RunCi.hxml ├── extraParams.hxml ├── generate.hxml ├── haxelib.json ├── js └── jquery │ ├── Callbacks.hx │ ├── Config.hx │ ├── Deferred.hx │ ├── Error.hx │ ├── Event.hx │ ├── ExternGenerator.hx │ ├── Helper.hx │ ├── JQuery.hx │ ├── JqEltsIterator.hx │ ├── JqIterator.hx │ ├── JqXHR.hx │ ├── Plugin.hx │ ├── Promise.hx │ ├── Thenable.hx │ └── Utils.hx ├── package-lock.json ├── package.json ├── test.hxml └── test ├── DummyPlugin.hx ├── DummyPlugin2.hx ├── PhantomRunner.hx ├── RunCi.hx ├── Test.hx ├── TestExtern.hx ├── TestExternGenerator.hx ├── TestNode.hx ├── TestPlugin.hx ├── TestUtils.hx └── bin └── test.html /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jQueryExternForHaxe", 3 | "dockerComposeFile": "docker-compose.yml", 4 | "service": "workspace", 5 | "workspaceFolder": "/workspace", 6 | "remoteEnv": { 7 | "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" 8 | }, 9 | "settings": {}, 10 | "extensions": [ 11 | "ms-azuretools.vscode-docker", 12 | "nadako.vshaxe", 13 | "earthly.earthfile-syntax-highlighting", 14 | ], 15 | "remoteUser": "vscode" 16 | } -------------------------------------------------------------------------------- /.devcontainer/direnv.toml: -------------------------------------------------------------------------------- 1 | [whitelist] 2 | prefix = [ "/workspace" ] -------------------------------------------------------------------------------- /.devcontainer/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | workspace: 4 | image: ghcr.io/andyli/jqueryexternforhaxe_devcontainer:master 5 | init: true 6 | volumes: 7 | - /var/run/docker.sock:/var/run/docker-host.sock 8 | - ..:/workspace:cached 9 | environment: 10 | - EARTHLY_BUILDKIT_HOST=tcp://earthly:8372 11 | - EARTHLY_USE_INLINE_CACHE=true 12 | - EARTHLY_SAVE_INLINE_CACHE=true 13 | user: vscode 14 | entrypoint: /usr/local/share/docker-init.sh 15 | command: sleep infinity 16 | earthly: 17 | image: earthly/buildkitd:v0.6.4 18 | privileged: true 19 | environment: 20 | - BUILDKIT_TCP_TRANSPORT_ENABLED=true 21 | expose: 22 | - 8372 23 | volumes: 24 | # https://docs.earthly.dev/docs/guides/using-the-earthly-docker-images/buildkit-standalone#earthly_tmp_dir 25 | - earthly-tmp:/tmp/earthly:rw 26 | 27 | volumes: 28 | earthly-tmp: 29 | -------------------------------------------------------------------------------- /.devcontainer/library-scripts/common-debian.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #------------------------------------------------------------------------------------------------------------- 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. 5 | #------------------------------------------------------------------------------------------------------------- 6 | # 7 | # Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/common.md 8 | # Maintainer: The VS Code and Codespaces Teams 9 | # 10 | # Syntax: ./common-debian.sh [install zsh flag] [username] [user UID] [user GID] [upgrade packages flag] [install Oh My Zsh! flag] [Add non-free packages] 11 | 12 | set -e 13 | 14 | INSTALL_ZSH=${1:-"true"} 15 | USERNAME=${2:-"automatic"} 16 | USER_UID=${3:-"automatic"} 17 | USER_GID=${4:-"automatic"} 18 | UPGRADE_PACKAGES=${5:-"true"} 19 | INSTALL_OH_MYS=${6:-"true"} 20 | ADD_NON_FREE_PACKAGES=${7:-"false"} 21 | SCRIPT_DIR="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)" 22 | MARKER_FILE="/usr/local/etc/vscode-dev-containers/common" 23 | 24 | if [ "$(id -u)" -ne 0 ]; then 25 | echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' 26 | exit 1 27 | fi 28 | 29 | # Ensure that login shells get the correct path if the user updated the PATH using ENV. 30 | rm -f /etc/profile.d/00-restore-env.sh 31 | echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh 32 | chmod +x /etc/profile.d/00-restore-env.sh 33 | 34 | # If in automatic mode, determine if a user already exists, if not use vscode 35 | if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then 36 | USERNAME="" 37 | POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)") 38 | for CURRENT_USER in ${POSSIBLE_USERS[@]}; do 39 | if id -u ${CURRENT_USER} > /dev/null 2>&1; then 40 | USERNAME=${CURRENT_USER} 41 | break 42 | fi 43 | done 44 | if [ "${USERNAME}" = "" ]; then 45 | USERNAME=vscode 46 | fi 47 | elif [ "${USERNAME}" = "none" ]; then 48 | USERNAME=root 49 | USER_UID=0 50 | USER_GID=0 51 | fi 52 | 53 | # Load markers to see which steps have already run 54 | if [ -f "${MARKER_FILE}" ]; then 55 | echo "Marker file found:" 56 | cat "${MARKER_FILE}" 57 | source "${MARKER_FILE}" 58 | fi 59 | 60 | # Ensure apt is in non-interactive to avoid prompts 61 | export DEBIAN_FRONTEND=noninteractive 62 | 63 | # Function to call apt-get if needed 64 | apt_get_update_if_needed() 65 | { 66 | if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then 67 | echo "Running apt-get update..." 68 | apt-get update 69 | else 70 | echo "Skipping apt-get update." 71 | fi 72 | } 73 | 74 | # Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies 75 | if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then 76 | 77 | package_list="apt-utils \ 78 | openssh-client \ 79 | gnupg2 \ 80 | dirmngr \ 81 | iproute2 \ 82 | procps \ 83 | lsof \ 84 | htop \ 85 | net-tools \ 86 | psmisc \ 87 | curl \ 88 | wget \ 89 | rsync \ 90 | ca-certificates \ 91 | unzip \ 92 | zip \ 93 | nano \ 94 | vim-tiny \ 95 | less \ 96 | jq \ 97 | lsb-release \ 98 | apt-transport-https \ 99 | dialog \ 100 | libc6 \ 101 | libgcc1 \ 102 | libkrb5-3 \ 103 | libgssapi-krb5-2 \ 104 | libicu[0-9][0-9] \ 105 | liblttng-ust0 \ 106 | libstdc++6 \ 107 | zlib1g \ 108 | locales \ 109 | sudo \ 110 | ncdu \ 111 | man-db \ 112 | strace \ 113 | manpages \ 114 | manpages-dev \ 115 | init-system-helpers" 116 | 117 | # Needed for adding manpages-posix and manpages-posix-dev which are non-free packages in Debian 118 | if [ "${ADD_NON_FREE_PACKAGES}" = "true" ]; then 119 | # Bring in variables from /etc/os-release like VERSION_CODENAME 120 | . /etc/os-release 121 | sed -i -E "s/deb http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME} main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME} main contrib non-free/" /etc/apt/sources.list 122 | sed -i -E "s/deb-src http:\/\/(deb|httredir)\.debian\.org\/debian ${VERSION_CODENAME} main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME} main contrib non-free/" /etc/apt/sources.list 123 | sed -i -E "s/deb http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list 124 | sed -i -E "s/deb-src http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list 125 | sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list 126 | sed -i "s/deb-src http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list 127 | sed -i "s/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list 128 | sed -i "s/deb-src http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list 129 | # Handle bullseye location for security https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.en.html 130 | sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main contrib non-free/" /etc/apt/sources.list 131 | sed -i "s/deb-src http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}-security main contrib non-free/" /etc/apt/sources.list 132 | echo "Running apt-get update..." 133 | apt-get update 134 | package_list="${package_list} manpages-posix manpages-posix-dev" 135 | else 136 | apt_get_update_if_needed 137 | fi 138 | 139 | # Install libssl1.1 if available 140 | if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then 141 | package_list="${package_list} libssl1.1" 142 | fi 143 | 144 | # Install appropriate version of libssl1.0.x if available 145 | libssl_package=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '') 146 | if [ "$(echo "$LIlibssl_packageBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then 147 | if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then 148 | # Debian 9 149 | package_list="${package_list} libssl1.0.2" 150 | elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then 151 | # Ubuntu 18.04, 16.04, earlier 152 | package_list="${package_list} libssl1.0.0" 153 | fi 154 | fi 155 | 156 | echo "Packages to verify are installed: ${package_list}" 157 | apt-get -y install --no-install-recommends ${package_list} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 ) 158 | 159 | # Install git if not already installed (may be more recent than distro version) 160 | if ! type git > /dev/null 2>&1; then 161 | apt-get -y install --no-install-recommends git 162 | fi 163 | 164 | PACKAGES_ALREADY_INSTALLED="true" 165 | fi 166 | 167 | # Get to latest versions of all packages 168 | if [ "${UPGRADE_PACKAGES}" = "true" ]; then 169 | apt_get_update_if_needed 170 | apt-get -y upgrade --no-install-recommends 171 | apt-get autoremove -y 172 | fi 173 | 174 | # Ensure at least the en_US.UTF-8 UTF-8 locale is available. 175 | # Common need for both applications and things like the agnoster ZSH theme. 176 | if [ "${LOCALE_ALREADY_SET}" != "true" ] && ! grep -o -E '^\s*en_US.UTF-8\s+UTF-8' /etc/locale.gen > /dev/null; then 177 | echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen 178 | locale-gen 179 | LOCALE_ALREADY_SET="true" 180 | fi 181 | 182 | # Create or update a non-root user to match UID/GID. 183 | group_name="${USERNAME}" 184 | if id -u ${USERNAME} > /dev/null 2>&1; then 185 | # User exists, update if needed 186 | if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -g $USERNAME)" ]; then 187 | group_name="$(id -gn $USERNAME)" 188 | groupmod --gid $USER_GID ${group_name} 189 | usermod --gid $USER_GID $USERNAME 190 | fi 191 | if [ "${USER_UID}" != "automatic" ] && [ "$USER_UID" != "$(id -u $USERNAME)" ]; then 192 | usermod --uid $USER_UID $USERNAME 193 | fi 194 | else 195 | # Create user 196 | if [ "${USER_GID}" = "automatic" ]; then 197 | groupadd $USERNAME 198 | else 199 | groupadd --gid $USER_GID $USERNAME 200 | fi 201 | if [ "${USER_UID}" = "automatic" ]; then 202 | useradd -s /bin/bash --gid $USERNAME -m $USERNAME 203 | else 204 | useradd -s /bin/bash --uid $USER_UID --gid $USERNAME -m $USERNAME 205 | fi 206 | fi 207 | 208 | # Add add sudo support for non-root user 209 | if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then 210 | echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME 211 | chmod 0440 /etc/sudoers.d/$USERNAME 212 | EXISTING_NON_ROOT_USER="${USERNAME}" 213 | fi 214 | 215 | # ** Shell customization section ** 216 | if [ "${USERNAME}" = "root" ]; then 217 | user_rc_path="/root" 218 | else 219 | user_rc_path="/home/${USERNAME}" 220 | fi 221 | 222 | # Restore user .bashrc defaults from skeleton file if it doesn't exist or is empty 223 | if [ ! -f "${user_rc_path}/.bashrc" ] || [ ! -s "${user_rc_path}/.bashrc" ] ; then 224 | cp /etc/skel/.bashrc "${user_rc_path}/.bashrc" 225 | fi 226 | 227 | # Restore user .profile defaults from skeleton file if it doesn't exist or is empty 228 | if [ ! -f "${user_rc_path}/.profile" ] || [ ! -s "${user_rc_path}/.profile" ] ; then 229 | cp /etc/skel/.profile "${user_rc_path}/.profile" 230 | fi 231 | 232 | # .bashrc/.zshrc snippet 233 | rc_snippet="$(cat << 'EOF' 234 | 235 | if [ -z "${USER}" ]; then export USER=$(whoami); fi 236 | if [[ "${PATH}" != *"$HOME/.local/bin"* ]]; then export PATH="${PATH}:$HOME/.local/bin"; fi 237 | 238 | # Display optional first run image specific notice if configured and terminal is interactive 239 | if [ -t 1 ] && [[ "${TERM_PROGRAM}" = "vscode" || "${TERM_PROGRAM}" = "codespaces" ]] && [ ! -f "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed" ]; then 240 | if [ -f "/usr/local/etc/vscode-dev-containers/first-run-notice.txt" ]; then 241 | cat "/usr/local/etc/vscode-dev-containers/first-run-notice.txt" 242 | elif [ -f "/workspaces/.codespaces/shared/first-run-notice.txt" ]; then 243 | cat "/workspaces/.codespaces/shared/first-run-notice.txt" 244 | fi 245 | mkdir -p "$HOME/.config/vscode-dev-containers" 246 | # Mark first run notice as displayed after 10s to avoid problems with fast terminal refreshes hiding it 247 | ((sleep 10s; touch "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed") &) 248 | fi 249 | 250 | # Set the default git editor if not already set 251 | if [ -z "$(git config --get core.editor)" ] && [ -z "${GIT_EDITOR}" ]; then 252 | if [ "${TERM_PROGRAM}" = "vscode" ]; then 253 | if [[ -n $(command -v code-insiders) && -z $(command -v code) ]]; then 254 | export GIT_EDITOR="code-insiders --wait" 255 | else 256 | export GIT_EDITOR="code --wait" 257 | fi 258 | fi 259 | fi 260 | 261 | EOF 262 | )" 263 | 264 | # code shim, it fallbacks to code-insiders if code is not available 265 | cat << 'EOF' > /usr/local/bin/code 266 | #!/bin/sh 267 | 268 | get_in_path_except_current() { 269 | which -a "$1" | grep -A1 "$0" | grep -v "$0" 270 | } 271 | 272 | code="$(get_in_path_except_current code)" 273 | 274 | if [ -n "$code" ]; then 275 | exec "$code" "$@" 276 | elif [ "$(command -v code-insiders)" ]; then 277 | exec code-insiders "$@" 278 | else 279 | echo "code or code-insiders is not installed" >&2 280 | exit 127 281 | fi 282 | EOF 283 | chmod +x /usr/local/bin/code 284 | 285 | # systemctl shim - tells people to use 'service' if systemd is not running 286 | cat << 'EOF' > /usr/local/bin/systemctl 287 | #!/bin/sh 288 | set -e 289 | if [ -d "/run/systemd/system" ]; then 290 | exec /bin/systemctl/systemctl "$@" 291 | else 292 | echo '\n"systemd" is not running in this container due to its overhead.\nUse the "service" command to start services intead. e.g.: \n\nservice --status-all' 293 | fi 294 | EOF 295 | chmod +x /usr/local/bin/systemctl 296 | 297 | # Codespaces bash and OMZ themes - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/robbyrussell.zsh-theme 298 | codespaces_bash="$(cat \ 299 | <<'EOF' 300 | 301 | # Codespaces bash prompt theme 302 | __bash_prompt() { 303 | local userpart='`export XIT=$? \ 304 | && [ ! -z "${GITHUB_USER}" ] && echo -n "\[\033[0;32m\]@${GITHUB_USER} " || echo -n "\[\033[0;32m\]\u " \ 305 | && [ "$XIT" -ne "0" ] && echo -n "\[\033[1;31m\]➜" || echo -n "\[\033[0m\]➜"`' 306 | local gitbranch='`\ 307 | if [ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ]; then \ 308 | export BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null); \ 309 | if [ "${BRANCH}" != "" ]; then \ 310 | echo -n "\[\033[0;36m\](\[\033[1;31m\]${BRANCH}" \ 311 | && if git ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \ 312 | echo -n " \[\033[1;33m\]✗"; \ 313 | fi \ 314 | && echo -n "\[\033[0;36m\]) "; \ 315 | fi; \ 316 | fi`' 317 | local lightblue='\[\033[1;34m\]' 318 | local removecolor='\[\033[0m\]' 319 | PS1="${userpart} ${lightblue}\w ${gitbranch}${removecolor}\$ " 320 | unset -f __bash_prompt 321 | } 322 | __bash_prompt 323 | 324 | EOF 325 | )" 326 | 327 | codespaces_zsh="$(cat \ 328 | <<'EOF' 329 | # Codespaces zsh prompt theme 330 | __zsh_prompt() { 331 | local prompt_username 332 | if [ ! -z "${GITHUB_USER}" ]; then 333 | prompt_username="@${GITHUB_USER}" 334 | else 335 | prompt_username="%n" 336 | fi 337 | PROMPT="%{$fg[green]%}${prompt_username} %(?:%{$reset_color%}➜ :%{$fg_bold[red]%}➜ )" # User/exit code arrow 338 | PROMPT+='%{$fg_bold[blue]%}%(5~|%-1~/…/%3~|%4~)%{$reset_color%} ' # cwd 339 | PROMPT+='$([ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ] && git_prompt_info)' # Git status 340 | PROMPT+='%{$fg[white]%}$ %{$reset_color%}' 341 | unset -f __zsh_prompt 342 | } 343 | ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[cyan]%}(%{$fg_bold[red]%}" 344 | ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} " 345 | ZSH_THEME_GIT_PROMPT_DIRTY=" %{$fg_bold[yellow]%}✗%{$fg_bold[cyan]%})" 346 | ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[cyan]%})" 347 | __zsh_prompt 348 | 349 | EOF 350 | )" 351 | 352 | # Add RC snippet and custom bash prompt 353 | if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then 354 | echo "${rc_snippet}" >> /etc/bash.bashrc 355 | echo "${codespaces_bash}" >> "${user_rc_path}/.bashrc" 356 | echo 'export PROMPT_DIRTRIM=4' >> "${user_rc_path}/.bashrc" 357 | if [ "${USERNAME}" != "root" ]; then 358 | echo "${codespaces_bash}" >> "/root/.bashrc" 359 | echo 'export PROMPT_DIRTRIM=4' >> "/root/.bashrc" 360 | fi 361 | chown ${USERNAME}:${group_name} "${user_rc_path}/.bashrc" 362 | RC_SNIPPET_ALREADY_ADDED="true" 363 | fi 364 | 365 | # Optionally install and configure zsh and Oh My Zsh! 366 | if [ "${INSTALL_ZSH}" = "true" ]; then 367 | if ! type zsh > /dev/null 2>&1; then 368 | apt_get_update_if_needed 369 | apt-get install -y zsh 370 | fi 371 | if [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then 372 | echo "${rc_snippet}" >> /etc/zsh/zshrc 373 | ZSH_ALREADY_INSTALLED="true" 374 | fi 375 | 376 | # Adapted, simplified inline Oh My Zsh! install steps that adds, defaults to a codespaces theme. 377 | # See https://github.com/ohmyzsh/ohmyzsh/blob/master/tools/install.sh for official script. 378 | oh_my_install_dir="${user_rc_path}/.oh-my-zsh" 379 | if [ ! -d "${oh_my_install_dir}" ] && [ "${INSTALL_OH_MYS}" = "true" ]; then 380 | template_path="${oh_my_install_dir}/templates/zshrc.zsh-template" 381 | user_rc_file="${user_rc_path}/.zshrc" 382 | umask g-w,o-w 383 | mkdir -p ${oh_my_install_dir} 384 | git clone --depth=1 \ 385 | -c core.eol=lf \ 386 | -c core.autocrlf=false \ 387 | -c fsck.zeroPaddedFilemode=ignore \ 388 | -c fetch.fsck.zeroPaddedFilemode=ignore \ 389 | -c receive.fsck.zeroPaddedFilemode=ignore \ 390 | "https://github.com/ohmyzsh/ohmyzsh" "${oh_my_install_dir}" 2>&1 391 | echo -e "$(cat "${template_path}")\nDISABLE_AUTO_UPDATE=true\nDISABLE_UPDATE_PROMPT=true" > ${user_rc_file} 392 | sed -i -e 's/ZSH_THEME=.*/ZSH_THEME="codespaces"/g' ${user_rc_file} 393 | 394 | mkdir -p ${oh_my_install_dir}/custom/themes 395 | echo "${codespaces_zsh}" > "${oh_my_install_dir}/custom/themes/codespaces.zsh-theme" 396 | # Shrink git while still enabling updates 397 | cd "${oh_my_install_dir}" 398 | git repack -a -d -f --depth=1 --window=1 399 | # Copy to non-root user if one is specified 400 | if [ "${USERNAME}" != "root" ]; then 401 | cp -rf "${user_rc_file}" "${oh_my_install_dir}" /root 402 | chown -R ${USERNAME}:${group_name} "${user_rc_path}" 403 | fi 404 | fi 405 | fi 406 | 407 | # Persist image metadata info, script if meta.env found in same directory 408 | meta_info_script="$(cat << 'EOF' 409 | #!/bin/sh 410 | . /usr/local/etc/vscode-dev-containers/meta.env 411 | 412 | # Minimal output 413 | if [ "$1" = "version" ] || [ "$1" = "image-version" ]; then 414 | echo "${VERSION}" 415 | exit 0 416 | elif [ "$1" = "release" ]; then 417 | echo "${GIT_REPOSITORY_RELEASE}" 418 | exit 0 419 | elif [ "$1" = "content" ] || [ "$1" = "content-url" ] || [ "$1" = "contents" ] || [ "$1" = "contents-url" ]; then 420 | echo "${CONTENTS_URL}" 421 | exit 0 422 | fi 423 | 424 | #Full output 425 | echo 426 | echo "Development container image information" 427 | echo 428 | if [ ! -z "${VERSION}" ]; then echo "- Image version: ${VERSION}"; fi 429 | if [ ! -z "${DEFINITION_ID}" ]; then echo "- Definition ID: ${DEFINITION_ID}"; fi 430 | if [ ! -z "${VARIANT}" ]; then echo "- Variant: ${VARIANT}"; fi 431 | if [ ! -z "${GIT_REPOSITORY}" ]; then echo "- Source code repository: ${GIT_REPOSITORY}"; fi 432 | if [ ! -z "${GIT_REPOSITORY_RELEASE}" ]; then echo "- Source code release/branch: ${GIT_REPOSITORY_RELEASE}"; fi 433 | if [ ! -z "${BUILD_TIMESTAMP}" ]; then echo "- Timestamp: ${BUILD_TIMESTAMP}"; fi 434 | if [ ! -z "${CONTENTS_URL}" ]; then echo && echo "More info: ${CONTENTS_URL}"; fi 435 | echo 436 | EOF 437 | )" 438 | if [ -f "${SCRIPT_DIR}/meta.env" ]; then 439 | mkdir -p /usr/local/etc/vscode-dev-containers/ 440 | cp -f "${SCRIPT_DIR}/meta.env" /usr/local/etc/vscode-dev-containers/meta.env 441 | echo "${meta_info_script}" > /usr/local/bin/devcontainer-info 442 | chmod +x /usr/local/bin/devcontainer-info 443 | fi 444 | 445 | # Write marker file 446 | mkdir -p "$(dirname "${MARKER_FILE}")" 447 | echo -e "\ 448 | PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\ 449 | LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\ 450 | EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\ 451 | RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\ 452 | ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}" 453 | 454 | echo "Done!" 455 | -------------------------------------------------------------------------------- /.devcontainer/library-scripts/docker-debian.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #------------------------------------------------------------------------------------------------------------- 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. 5 | #------------------------------------------------------------------------------------------------------------- 6 | # 7 | # Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker.md 8 | # Maintainer: The VS Code and Codespaces Teams 9 | # 10 | # Syntax: ./docker-debian.sh [enable non-root docker socket access flag] [source socket] [target socket] [non-root user] [use moby] [CLI version] 11 | 12 | ENABLE_NONROOT_DOCKER=${1:-"true"} 13 | SOURCE_SOCKET=${2:-"/var/run/docker-host.sock"} 14 | TARGET_SOCKET=${3:-"/var/run/docker.sock"} 15 | USERNAME=${4:-"automatic"} 16 | USE_MOBY=${5:-"true"} 17 | DOCKER_VERSION=${6:-"latest"} 18 | MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc" 19 | DOCKER_DASH_COMPOSE_VERSION="1" 20 | 21 | set -e 22 | 23 | if [ "$(id -u)" -ne 0 ]; then 24 | echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' 25 | exit 1 26 | fi 27 | 28 | # Determine the appropriate non-root user 29 | if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then 30 | USERNAME="" 31 | POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)") 32 | for CURRENT_USER in ${POSSIBLE_USERS[@]}; do 33 | if id -u ${CURRENT_USER} > /dev/null 2>&1; then 34 | USERNAME=${CURRENT_USER} 35 | break 36 | fi 37 | done 38 | if [ "${USERNAME}" = "" ]; then 39 | USERNAME=root 40 | fi 41 | elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then 42 | USERNAME=root 43 | fi 44 | 45 | # Get central common setting 46 | get_common_setting() { 47 | if [ "${common_settings_file_loaded}" != "true" ]; then 48 | curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping." 49 | common_settings_file_loaded=true 50 | fi 51 | if [ -f "/tmp/vsdc-settings.env" ]; then 52 | local multi_line="" 53 | if [ "$2" = "true" ]; then multi_line="-z"; fi 54 | local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')" 55 | if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi 56 | fi 57 | echo "$1=${!1}" 58 | } 59 | 60 | # Function to run apt-get if needed 61 | apt_get_update_if_needed() 62 | { 63 | if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then 64 | echo "Running apt-get update..." 65 | apt-get update 66 | else 67 | echo "Skipping apt-get update." 68 | fi 69 | } 70 | 71 | # Checks if packages are installed and installs them if not 72 | check_packages() { 73 | if ! dpkg -s "$@" > /dev/null 2>&1; then 74 | apt_get_update_if_needed 75 | apt-get -y install --no-install-recommends "$@" 76 | fi 77 | } 78 | 79 | # Figure out correct version of a three part version number is not passed 80 | find_version_from_git_tags() { 81 | local variable_name=$1 82 | local requested_version=${!variable_name} 83 | if [ "${requested_version}" = "none" ]; then return; fi 84 | local repository=$2 85 | local prefix=${3:-"tags/v"} 86 | local separator=${4:-"."} 87 | local last_part_optional=${5:-"false"} 88 | if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then 89 | local escaped_separator=${separator//./\\.} 90 | local last_part 91 | if [ "${last_part_optional}" = "true" ]; then 92 | last_part="(${escaped_separator}[0-9]+)?" 93 | else 94 | last_part="${escaped_separator}[0-9]+" 95 | fi 96 | local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$" 97 | local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)" 98 | if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then 99 | declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)" 100 | else 101 | set +e 102 | declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")" 103 | set -e 104 | fi 105 | fi 106 | if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then 107 | echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2 108 | exit 1 109 | fi 110 | echo "${variable_name}=${!variable_name}" 111 | } 112 | 113 | # Ensure apt is in non-interactive to avoid prompts 114 | export DEBIAN_FRONTEND=noninteractive 115 | 116 | # Install dependencies 117 | check_packages apt-transport-https curl ca-certificates gnupg2 dirmngr 118 | if ! type git > /dev/null 2>&1; then 119 | apt_get_update_if_needed 120 | apt-get -y install git 121 | fi 122 | 123 | # Source /etc/os-release to get OS info 124 | . /etc/os-release 125 | # Fetch host/container arch. 126 | architecture="$(dpkg --print-architecture)" 127 | 128 | # Set up the necessary apt repos (either Microsoft's or Docker's) 129 | if [ "${USE_MOBY}" = "true" ]; then 130 | 131 | cli_package_name="moby-cli" 132 | 133 | # Import key safely and import Microsoft apt repo 134 | get_common_setting MICROSOFT_GPG_KEYS_URI 135 | curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg 136 | echo "deb [arch=${architecture} signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list 137 | else 138 | # Name of proprietary engine package 139 | cli_package_name="docker-ce-cli" 140 | 141 | # Import key safely and import Docker apt repo 142 | curl -fsSL https://download.docker.com/linux/${ID}/gpg | gpg --dearmor > /usr/share/keyrings/docker-archive-keyring.gpg 143 | echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" > /etc/apt/sources.list.d/docker.list 144 | fi 145 | 146 | # Refresh apt lists 147 | apt-get update 148 | 149 | # Soft version matching for CLI 150 | if [ "${DOCKER_VERSION}" = "latest" ] || [ "${DOCKER_VERSION}" = "lts" ] || [ "${DOCKER_VERSION}" = "stable" ]; then 151 | # Empty, meaning grab whatever "latest" is in apt repo 152 | cli_version_suffix="" 153 | else 154 | # Fetch a valid version from the apt-cache (eg: the Microsoft repo appends +azure, breakfix, etc...) 155 | docker_version_dot_escaped="${DOCKER_VERSION//./\\.}" 156 | docker_version_dot_plus_escaped="${docker_version_dot_escaped//+/\\+}" 157 | # Regex needs to handle debian package version number format: https://www.systutorials.com/docs/linux/man/5-deb-version/ 158 | docker_version_regex="^(.+:)?${docker_version_dot_plus_escaped}([\\.\\+ ~:-]|$)" 159 | set +e # Don't exit if finding version fails - will handle gracefully 160 | cli_version_suffix="=$(apt-cache madison ${cli_package_name} | awk -F"|" '{print $2}' | sed -e 's/^[ \t]*//' | grep -E -m 1 "${docker_version_regex}")" 161 | set -e 162 | if [ -z "${cli_version_suffix}" ] || [ "${cli_version_suffix}" = "=" ]; then 163 | echo "(!) No full or partial Docker / Moby version match found for \"${DOCKER_VERSION}\" on OS ${ID} ${VERSION_CODENAME} (${architecture}). Available versions:" 164 | apt-cache madison ${cli_package_name} | awk -F"|" '{print $2}' | grep -oP '^(.+:)?\K.+' 165 | exit 1 166 | fi 167 | echo "cli_version_suffix ${cli_version_suffix}" 168 | fi 169 | 170 | # Install Docker / Moby CLI if not already installed 171 | if type docker > /dev/null 2>&1; then 172 | echo "Docker / Moby CLI already installed." 173 | else 174 | if [ "${USE_MOBY}" = "true" ]; then 175 | apt-get -y install --no-install-recommends moby-cli${cli_version_suffix} moby-buildx 176 | apt-get -y install --no-install-recommends moby-compose || echo "(*) Package moby-compose (Docker Compose v2) not available for OS ${ID} ${VERSION_CODENAME} (${architecture}). Skipping." 177 | else 178 | apt-get -y install --no-install-recommends docker-ce-cli${cli_version_suffix} 179 | fi 180 | fi 181 | 182 | # Install Docker Compose if not already installed and is on a supported architecture 183 | if type docker-compose > /dev/null 2>&1; then 184 | echo "Docker Compose already installed." 185 | else 186 | TARGET_COMPOSE_ARCH="$(uname -m)" 187 | if [ "${TARGET_COMPOSE_ARCH}" = "amd64" ]; then 188 | TARGET_COMPOSE_ARCH="x86_64" 189 | fi 190 | if [ "${TARGET_COMPOSE_ARCH}" != "x86_64" ]; then 191 | # Use pip to get a version that runns on this architecture 192 | if ! dpkg -s python3-minimal python3-pip libffi-dev python3-venv > /dev/null 2>&1; then 193 | apt_get_update_if_needed 194 | apt-get -y install python3-minimal python3-pip libffi-dev python3-venv 195 | fi 196 | export PIPX_HOME=/usr/local/pipx 197 | mkdir -p ${PIPX_HOME} 198 | export PIPX_BIN_DIR=/usr/local/bin 199 | export PYTHONUSERBASE=/tmp/pip-tmp 200 | export PIP_CACHE_DIR=/tmp/pip-tmp/cache 201 | pipx_bin=pipx 202 | if ! type pipx > /dev/null 2>&1; then 203 | pip3 install --disable-pip-version-check --no-cache-dir --user pipx 204 | pipx_bin=/tmp/pip-tmp/bin/pipx 205 | fi 206 | ${pipx_bin} install --pip-args '--no-cache-dir --force-reinstall' docker-compose 207 | rm -rf /tmp/pip-tmp 208 | else 209 | find_version_from_git_tags DOCKER_DASH_COMPOSE_VERSION "https://github.com/docker/compose" "tags/" 210 | echo "(*) Installing docker-compose ${DOCKER_DASH_COMPOSE_VERSION}..." 211 | curl -fsSL "https://github.com/docker/compose/releases/download/${DOCKER_DASH_COMPOSE_VERSION}/docker-compose-Linux-x86_64" -o /usr/local/bin/docker-compose 212 | chmod +x /usr/local/bin/docker-compose 213 | fi 214 | fi 215 | 216 | # If init file already exists, exit 217 | if [ -f "/usr/local/share/docker-init.sh" ]; then 218 | exit 0 219 | fi 220 | echo "docker-init doesnt exist, adding..." 221 | 222 | # By default, make the source and target sockets the same 223 | if [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ]; then 224 | touch "${SOURCE_SOCKET}" 225 | ln -s "${SOURCE_SOCKET}" "${TARGET_SOCKET}" 226 | fi 227 | 228 | # Add a stub if not adding non-root user access, user is root 229 | if [ "${ENABLE_NONROOT_DOCKER}" = "false" ] || [ "${USERNAME}" = "root" ]; then 230 | echo '/usr/bin/env bash -c "\$@"' > /usr/local/share/docker-init.sh 231 | chmod +x /usr/local/share/docker-init.sh 232 | exit 0 233 | fi 234 | 235 | # If enabling non-root access and specified user is found, setup socat and add script 236 | chown -h "${USERNAME}":root "${TARGET_SOCKET}" 237 | if ! dpkg -s socat > /dev/null 2>&1; then 238 | apt_get_update_if_needed 239 | apt-get -y install socat 240 | fi 241 | tee /usr/local/share/docker-init.sh > /dev/null \ 242 | << EOF 243 | #!/usr/bin/env bash 244 | #------------------------------------------------------------------------------------------------------------- 245 | # Copyright (c) Microsoft Corporation. All rights reserved. 246 | # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. 247 | #------------------------------------------------------------------------------------------------------------- 248 | 249 | set -e 250 | 251 | SOCAT_PATH_BASE=/tmp/vscr-docker-from-docker 252 | SOCAT_LOG=\${SOCAT_PATH_BASE}.log 253 | SOCAT_PID=\${SOCAT_PATH_BASE}.pid 254 | 255 | # Wrapper function to only use sudo if not already root 256 | sudoIf() 257 | { 258 | if [ "\$(id -u)" -ne 0 ]; then 259 | sudo "\$@" 260 | else 261 | "\$@" 262 | fi 263 | } 264 | 265 | # Log messages 266 | log() 267 | { 268 | echo -e "[\$(date)] \$@" | sudoIf tee -a \${SOCAT_LOG} > /dev/null 269 | } 270 | 271 | echo -e "\n** \$(date) **" | sudoIf tee -a \${SOCAT_LOG} > /dev/null 272 | log "Ensuring ${USERNAME} has access to ${SOURCE_SOCKET} via ${TARGET_SOCKET}" 273 | 274 | # If enabled, try to add a docker group with the right GID. If the group is root, 275 | # fall back on using socat to forward the docker socket to another unix socket so 276 | # that we can set permissions on it without affecting the host. 277 | if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ] && [ "${USERNAME}" != "root" ] && [ "${USERNAME}" != "0" ]; then 278 | SOCKET_GID=\$(stat -c '%g' ${SOURCE_SOCKET}) 279 | if [ "\${SOCKET_GID}" != "0" ]; then 280 | log "Adding user to group with GID \${SOCKET_GID}." 281 | if [ "\$(cat /etc/group | grep :\${SOCKET_GID}:)" = "" ]; then 282 | sudoIf groupadd --gid \${SOCKET_GID} docker-host 283 | fi 284 | # Add user to group if not already in it 285 | if [ "\$(id ${USERNAME} | grep -E "groups.*(=|,)\${SOCKET_GID}\(")" = "" ]; then 286 | sudoIf usermod -aG \${SOCKET_GID} ${USERNAME} 287 | fi 288 | else 289 | # Enable proxy if not already running 290 | if [ ! -f "\${SOCAT_PID}" ] || ! ps -p \$(cat \${SOCAT_PID}) > /dev/null; then 291 | log "Enabling socket proxy." 292 | log "Proxying ${SOURCE_SOCKET} to ${TARGET_SOCKET} for vscode" 293 | sudoIf rm -rf ${TARGET_SOCKET} 294 | (sudoIf socat UNIX-LISTEN:${TARGET_SOCKET},fork,mode=660,user=${USERNAME} UNIX-CONNECT:${SOURCE_SOCKET} 2>&1 | sudoIf tee -a \${SOCAT_LOG} > /dev/null & echo "\$!" | sudoIf tee \${SOCAT_PID} > /dev/null) 295 | else 296 | log "Socket proxy already running." 297 | fi 298 | fi 299 | log "Success" 300 | fi 301 | 302 | # Execute whatever commands were passed in (if any). This allows us 303 | # to set this script to ENTRYPOINT while still executing the default CMD. 304 | set +e 305 | exec "\$@" 306 | EOF 307 | chmod +x /usr/local/share/docker-init.sh 308 | chown ${USERNAME}:root /usr/local/share/docker-init.sh 309 | echo "Done!" -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: ["push", "pull_request"] 3 | 4 | env: 5 | EARTHLY_BUILDKIT_HOST: tcp://earthly:8372 6 | EARTHLY_USE_INLINE_CACHE: "true" 7 | EARTHLY_SAVE_INLINE_CACHE: "true" 8 | FORCE_COLOR: 1 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | container: ghcr.io/andyli/jqueryexternforhaxe_devcontainer:master 14 | services: 15 | earthly: 16 | image: earthly/buildkitd:v0.6.4 17 | options: --privileged 18 | env: 19 | BUILDKIT_TCP_TRANSPORT_ENABLED: "true" 20 | ports: 21 | - 8372 22 | volumes: 23 | - /tmp/earthly 24 | steps: 25 | - uses: actions/checkout@v2 26 | - name: Login to GitHub Container Registry 27 | uses: docker/login-action@v1 28 | with: 29 | registry: ghcr.io 30 | username: ${{ github.actor }} 31 | password: ${{ secrets.GITHUB_TOKEN }} 32 | - name: Build devcontainer 33 | run: earthly +ci-devcontainer --GIT_REF_NAME="${{ github.ref_name }}" --GIT_SHA="${{ github.sha }}" 34 | env: 35 | EARTHLY_PUSH: "${{ github.repository_owner == 'andyli' && github.event_name == 'push' }}" 36 | - name: Test 37 | run: earthly +test-all 38 | - name: Package 39 | run: earthly +package 40 | - uses: actions/upload-artifact@v2 41 | with: 42 | name: haxelib-zip 43 | path: jQueryExtern-*.zip 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | 4 | *.n 5 | *.js 6 | *.js.map 7 | api.xml 8 | node_modules 9 | .haxelib 10 | jQueryExtern-*.zip 11 | 12 | .envrc 13 | .tmp-earthly-out* 14 | -------------------------------------------------------------------------------- /Earthfile: -------------------------------------------------------------------------------- 1 | VERSION 0.6 2 | ARG UBUNTU_RELEASE=bionic 3 | FROM mcr.microsoft.com/vscode/devcontainers/base:0-$UBUNTU_RELEASE 4 | ARG DEVCONTAINER_IMAGE_NAME_DEFAULT=ghcr.io/andyli/jqueryexternforhaxe_devcontainer 5 | 6 | ARG USERNAME=vscode 7 | ARG USER_UID=1000 8 | ARG USER_GID=$USER_UID 9 | 10 | ARG WORKDIR=/workspace 11 | RUN mkdir -m 777 "$WORKDIR" 12 | WORKDIR "$WORKDIR" 13 | 14 | ARG HAXE_VERSION=4.2 15 | 16 | ARG --required TARGETARCH 17 | 18 | ghcr-login: 19 | LOCALLY 20 | RUN echo "$GITHUB_CR_PAT" | docker login ghcr.io -u "$GITHUB_USERNAME" --password-stdin 21 | 22 | devcontainer-library-scripts: 23 | RUN curl -fsSLO https://raw.githubusercontent.com/microsoft/vscode-dev-containers/main/script-library/common-debian.sh 24 | RUN curl -fsSLO https://raw.githubusercontent.com/microsoft/vscode-dev-containers/main/script-library/docker-debian.sh 25 | SAVE ARTIFACT --keep-ts *.sh AS LOCAL .devcontainer/library-scripts/ 26 | 27 | # Usage: 28 | # COPY +earthly/earthly /usr/local/bin/ 29 | # RUN earthly bootstrap --no-buildkit --with-autocomplete 30 | earthly: 31 | RUN curl -fsSL https://github.com/earthly/earthly/releases/download/v0.6.4/earthly-linux-${TARGETARCH} -o /usr/local/bin/earthly \ 32 | && chmod +x /usr/local/bin/earthly 33 | SAVE ARTIFACT /usr/local/bin/earthly 34 | 35 | haxelibs: 36 | FROM haxe:$HAXE_VERSION 37 | WORKDIR "$WORKDIR" 38 | RUN haxelib newrepo 39 | RUN haxelib install hxnodejs 40 | RUN haxelib install phantomjs 41 | RUN haxelib install utest 1.8.1 42 | RUN haxelib install mcli 43 | RUN haxelib dev jQueryExtern . 44 | SAVE ARTIFACT .haxelib 45 | 46 | devcontainer: 47 | # Avoid warnings by switching to noninteractive 48 | ENV DEBIAN_FRONTEND=noninteractive 49 | 50 | ARG INSTALL_ZSH="false" 51 | ARG UPGRADE_PACKAGES="true" 52 | ARG ENABLE_NONROOT_DOCKER="true" 53 | ARG USE_MOBY="false" 54 | COPY .devcontainer/library-scripts/common-debian.sh .devcontainer/library-scripts/docker-debian.sh /tmp/library-scripts/ 55 | RUN apt-get update \ 56 | && /bin/bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" "true" "true" \ 57 | && /bin/bash /tmp/library-scripts/docker-debian.sh "${ENABLE_NONROOT_DOCKER}" "/var/run/docker-host.sock" "/var/run/docker.sock" "${USERNAME}" "${USE_MOBY}" \ 58 | # Clean up 59 | && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts/ 60 | 61 | # Setting the ENTRYPOINT to docker-init.sh will configure non-root access 62 | # to the Docker socket. The script will also execute CMD as needed. 63 | ENTRYPOINT [ "/usr/local/share/docker-init.sh" ] 64 | CMD [ "sleep", "infinity" ] 65 | 66 | # Configure apt and install packages 67 | RUN apt-get update \ 68 | && apt-get install -qqy --no-install-recommends apt-utils dialog 2>&1 \ 69 | && apt-get install -qqy --no-install-recommends \ 70 | iproute2 \ 71 | procps \ 72 | sudo \ 73 | bash-completion \ 74 | build-essential \ 75 | cmake \ 76 | curl \ 77 | wget \ 78 | software-properties-common \ 79 | direnv \ 80 | tzdata \ 81 | # install docker engine for using `WITH DOCKER` 82 | docker-ce \ 83 | # install haxe 84 | && add-apt-repository ppa:haxe/haxe$HAXE_VERSION \ 85 | && apt-get install -qqy --no-install-recommends neko neko-dev haxe=1:$HAXE_VERSION.* \ 86 | # install a recent git 87 | && add-apt-repository ppa:git-core/ppa \ 88 | && apt-get install -qqy --no-install-recommends git \ 89 | # 90 | # Clean up 91 | && apt-get autoremove -y \ 92 | && apt-get clean -y \ 93 | && rm -rf /var/lib/apt/lists/* 94 | 95 | # Switch back to dialog for any ad-hoc use of apt-get 96 | ENV DEBIAN_FRONTEND= 97 | 98 | # Install earthly 99 | COPY +earthly/earthly /usr/local/bin/ 100 | RUN earthly bootstrap --no-buildkit --with-autocomplete 101 | 102 | USER $USERNAME 103 | 104 | # Config direnv 105 | COPY --chown=$USER_UID:$USER_GID .devcontainer/direnv.toml /home/$USERNAME/.config/direnv/config.toml 106 | 107 | # install haxelibs 108 | COPY --chown=$USER_UID:$USER_GID +haxelibs/.haxelib .haxelib 109 | VOLUME "$WORKDIR/.haxelib" 110 | 111 | # Config bash 112 | RUN echo 'eval "$(direnv hook bash)"' >> ~/.bashrc 113 | 114 | USER root 115 | 116 | ARG GIT_SHA 117 | ENV GIT_SHA="$GIT_SHA" 118 | ARG IMAGE_NAME="$DEVCONTAINER_IMAGE_NAME_DEFAULT" 119 | ARG IMAGE_TAG="master" 120 | ARG IMAGE_CACHE="$IMAGE_NAME:$IMAGE_TAG" 121 | SAVE IMAGE --cache-from="$IMAGE_CACHE" --push "$IMAGE_NAME:$IMAGE_TAG" 122 | 123 | ci-devcontainer: 124 | ARG --required GIT_SHA 125 | ARG --required GIT_REF_NAME 126 | BUILD +devcontainer \ 127 | --GIT_SHA="$GIT_SHA" \ 128 | --IMAGE_TAG="$GIT_SHA" \ 129 | --IMAGE_TAG="$GIT_REF_NAME" 130 | 131 | api-xml: 132 | RUN curl -fsSLO https://api.jquery.com/resources/api.xml 133 | SAVE ARTIFACT --keep-ts api.xml AS LOCAL ./api.xml 134 | 135 | extern-generator: 136 | FROM haxe:3.4 137 | 138 | # install haxelibs 139 | COPY --chown=$USER_UID:$USER_GID +haxelibs/.haxelib .haxelib 140 | VOLUME "$WORKDIR/.haxelib" 141 | 142 | # copy sources 143 | COPY js js 144 | COPY generate.hxml . 145 | 146 | RUN haxe generate.hxml 147 | SAVE ARTIFACT ExternGenerator.n 148 | 149 | generate-extern: 150 | FROM +devcontainer 151 | COPY +extern-generator/ExternGenerator.n ExternGenerator.n 152 | COPY api.xml . 153 | RUN neko ExternGenerator.n --api-xml api.xml --output-folder out --pack js.jquery --native '$' --use-element --use-haxe-either --use-haxe-rest --no-seperated-static --no-rename-static-field --add-haxe-iterator 154 | SAVE ARTIFACT --keep-ts out/js/jquery/*.hx AS LOCAL ./js/jquery/ 155 | 156 | node-modules: 157 | FROM node:16 158 | WORKDIR "$WORKDIR" 159 | COPY package.json package-lock.json . 160 | RUN npm i 161 | SAVE ARTIFACT node_modules 162 | 163 | test-runner: 164 | ARG HAXE_VERSION=4.2 165 | FROM haxe:$HAXE_VERSION 166 | WORKDIR "$WORKDIR" 167 | COPY --chown=$USER_UID:$USER_GID +haxelibs/.haxelib .haxelib 168 | COPY js js 169 | COPY test test 170 | COPY test.hxml extraParams.hxml . 171 | RUN haxe test.hxml -lib hxnodejs 172 | SAVE ARTIFACT test/bin/Test.js 173 | 174 | test: 175 | FROM node:16 176 | WORKDIR "$WORKDIR" 177 | ARG HAXE_VERSION=4.2 178 | COPY +node-modules/node_modules node_modules 179 | COPY test/bin/test.html test/bin/test.html 180 | COPY --build-arg HAXE_VERSION="$HAXE_VERSION" +test-runner/Test.js test/bin/Test.js 181 | RUN node test/bin/Test.js 182 | 183 | test-all: 184 | BUILD +test \ 185 | --HAXE_VERSION=4.2 \ 186 | --HAXE_VERSION=4.1 \ 187 | --HAXE_VERSION=4.0 \ 188 | --HAXE_VERSION=3.4 189 | 190 | package: 191 | COPY js js 192 | COPY haxelib.json extraParams.hxml README.md . 193 | RUN zip -FSr "jQueryExtern-$(jq -r '.version' haxelib.json).zip" js haxelib.json extraParams.hxml README.md 194 | SAVE ARTIFACT --keep-ts "jQueryExtern-*.zip" AS LOCAL . 195 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NOTICE 2 | 3 | This version of jQuery extern requires Haxe 3.3+. Users of Haxe 3.2.0- should checkout [jQueryExtern 2.0.4](https://github.com/andyli/jQueryExternForHaxe/tree/2.0.4). 4 | 5 | ------------------------ 6 | 7 | # jQueryExtern 8 | 9 | jQueryExtern unleash the full power of [jQuery](https://jquery.com/) in [Haxe](https://haxe.org/). Currently supports jQuery version up to *3.6.0*. 10 | 11 | This library, jQueryExtern, is a drop-in replacement of the externs in the standard library (`js.jquery.*`). It utilizes build macros to provide advanced control over the extern for all the special needs. 12 | 13 | jQueryExtern allows us to: 14 | * use a jQuery version other than the one supported in Haxe std lib (see [Version Selection](#version-selection)) 15 | * change how jQuery is referenced in output (see [Changing Native Reference](#changing-native-reference)) 16 | * create jQuery plugin externs (see [Plugin System](#plugin-system)) 17 | 18 | ## Download and Install 19 | 20 | Install via [haxelib](https://haxe.org/doc/haxelib/using_haxelib): 21 | ``` 22 | haxelib install jQueryExtern 23 | ``` 24 | 25 | Then add `-lib jQueryExtern` in our hxml. 26 | 27 | ## Usages 28 | 29 | ### Version Selection 30 | 31 | By default, jQueryExtern provides API same as the one supported by the std extern. It means that using jQueryExtern will not change the default jQuery version. The default jQuery is *1.6.4* in Haxe 3.2 and earlier. Since Haxe 3.3, the default version is set in compiler define `jquery-ver`. You may check the value of `jquery-ver` using [`haxe.macro.Compiler.getDefine`](https://api.haxe.org/haxe/macro/Compiler.html#getDefine). The version is encoded as an interger. e.g. 1.11.3 is encoded as 11103. 32 | 33 | jQueryExtern allows changing the supported jQuery version using `js.jquery.Config.setVersion`. It can be called in a hxml file like this: 34 | ```hxml 35 | --macro js.jquery.Config.setVersion('1.8.3') 36 | ``` 37 | The function will also set `jquery-ver` to the corresponding integer value automatically. 38 | 39 | ### Changing Native Reference 40 | 41 | jQuery in the JS output is referred as `$`, which is an alise of `jQuery`. Some JS libs, eg. [PrototypeJS](https://prototypejs.org/) also use the `$` variable, so we may want to refer jQuery by its original name instead. 42 | 43 | To do so, add the following compiler option: 44 | ```hxml 45 | --macro js.jquery.Config.setNative('jQuery') 46 | ``` 47 | Under the surface, it changes the metadata on the JQuery classes from `@:native("$")` to `@:native("jQuery")`. 48 | 49 | ### Plugin System 50 | 51 | jQueryExtern introduces the `js.jquery.Plugin` class to ease the process of writing jQuery plugin extern. It is macro-based, responsible for injecting additional fields to the `JQuery` extern class. 52 | 53 | To write a jQuery plugin extern, create an extern class that implements `js.jquery.Plugin`, and start writing the members **as if writing directly inside the `JQuery` extern class**. e.g.: 54 | 55 | ```haxe 56 | package jPlugin; 57 | extern class JQueryPlugIn implements js.jquery.Plugin { 58 | public function myMethod(arg:Dynamic):js.jquery.JQuery; 59 | static public function myStaticMethod(arg:Dynamic):Void; 60 | } 61 | ``` 62 | 63 | To use it, add the following compiler option: 64 | ```hxml 65 | --macro js.jquery.Config.addPlugin('jPlugin.JQueryPlugIn') 66 | ``` 67 | 68 | Note that currently import statements are not supported in the plugin extern modules. Please use fully-qualified names for types not existed in top-level or `js.jquery`. (see [#20](https://github.com/andyli/jQueryExternForHaxe/issues/20)) 69 | 70 | ## License 71 | 72 | jQueryExtern is released in the public domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 73 | 74 | jQuery's license can be found at https://jquery.org/license. 75 | -------------------------------------------------------------------------------- /RunCi.hxml: -------------------------------------------------------------------------------- 1 | -main PhantomRunner 2 | -cp test 3 | -lib phantomjs 4 | -lib utest 5 | -js test/bin/PhantomRunner.js 6 | 7 | --next 8 | 9 | -main RunCi 10 | -cp test 11 | -neko RunCi.n 12 | -cmd neko RunCi.n -------------------------------------------------------------------------------- /extraParams.hxml: -------------------------------------------------------------------------------- 1 | --macro js.jquery.Config.init() -------------------------------------------------------------------------------- /generate.hxml: -------------------------------------------------------------------------------- 1 | # Used for generating the externs 2 | -neko ExternGenerator.n 3 | -main js.jquery.ExternGenerator 4 | -lib mcli 5 | --macro allowPackage('js') 6 | --macro exclude('js.html.compat') 7 | # -cmd neko ExternGenerator.n --api-xml api.xml --output-folder . 8 | # -cmd neko ExternGenerator.n --api-xml api.xml --output-folder . --pack js.jquery --native '$' --use-element --use-haxe-either --use-haxe-rest --no-seperated-static --no-rename-static-field --add-haxe-iterator 9 | # -cmd neko ExternGenerator.n --api-xml api.xml --output-folder ~/Library/Caches/Homebrew/haxe--git/std --pack js.jquery --native '$' --no-build --use-element --use-haxe-either --use-haxe-rest --no-seperated-static --no-rename-static-field --add-haxe-iterator -------------------------------------------------------------------------------- /haxelib.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jQueryExtern", 3 | "url": "https://github.com/andyli/jQueryExternForHaxe", 4 | "license": "Public", 5 | "tags": ["js","extern"], 6 | "description": "Unleash the full power of jQuery in Haxe.", 7 | "version": "3.3.0", 8 | "releasenote": "Support jQuery version up to 3.6.0.", 9 | "contributors": ["andyli"] 10 | } -------------------------------------------------------------------------------- /js/jquery/Callbacks.hx: -------------------------------------------------------------------------------- 1 | /* This file is generated, do not edit! Visit https://api.jquery.com/ for API documentation. */ 2 | package js.jquery; 3 | @:build(js.jquery.Config.build()) extern class Callbacks { 4 | /** 5 | Add a callback or a collection of callbacks to a callback list. 6 | **/ 7 | @:jQueryVersion({ added : "1.7" }) 8 | public function add(callbacks:haxe.extern.EitherType>):js.jquery.Callbacks; 9 | /** 10 | Disable a callback list from doing anything more. 11 | **/ 12 | @:jQueryVersion({ added : "1.7" }) 13 | public function disable():js.jquery.Callbacks; 14 | /** 15 | Determine if the callbacks list has been disabled. 16 | **/ 17 | @:jQueryVersion({ added : "1.7" }) 18 | public function disabled():Bool; 19 | /** 20 | Remove all of the callbacks from a list. 21 | **/ 22 | @:jQueryVersion({ added : "1.7" }) 23 | public function empty():js.jquery.Callbacks; 24 | /** 25 | Call all of the callbacks with the given arguments. 26 | **/ 27 | @:jQueryVersion({ added : "1.7" }) 28 | public function fire(arguments:Dynamic):js.jquery.Callbacks; 29 | /** 30 | Call all callbacks in a list with the given context and arguments. 31 | **/ 32 | @:jQueryVersion({ added : "1.7" }) 33 | public function fireWith(?context:Dynamic, ?args:haxe.extern.EitherType, js.html.NodeList>):js.jquery.Callbacks; 34 | /** 35 | Determine if the callbacks have already been called at least once. 36 | **/ 37 | @:jQueryVersion({ added : "1.7" }) 38 | public function fired():Bool; 39 | /** 40 | Determine whether or not the list has any callbacks attached. If a callback is provided as an argument, determine whether it is in a list. 41 | **/ 42 | @:jQueryVersion({ added : "1.7" }) 43 | public function has(?callback:haxe.Constraints.Function):Bool; 44 | /** 45 | Lock a callback list in its current state. 46 | **/ 47 | @:jQueryVersion({ added : "1.7" }) 48 | public function lock():js.jquery.Callbacks; 49 | /** 50 | Determine if the callbacks list has been locked. 51 | **/ 52 | @:jQueryVersion({ added : "1.7" }) 53 | public function locked():Bool; 54 | /** 55 | A multi-purpose callbacks list object that provides a powerful way to manage callback lists. 56 | **/ 57 | @:selfCall 58 | @:jQueryVersion({ added : "1.7" }) 59 | public function new(flags:String):Void; 60 | /** 61 | Remove a callback or a collection of callbacks from a callback list. 62 | **/ 63 | @:jQueryVersion({ added : "1.7" }) 64 | public function remove(callbacks:haxe.extern.EitherType>):js.jquery.Callbacks; 65 | } -------------------------------------------------------------------------------- /js/jquery/Config.hx: -------------------------------------------------------------------------------- 1 | package js.jquery; 2 | 3 | import js.jquery.*; 4 | import haxe.macro.Expr; 5 | import haxe.macro.Context; 6 | import haxe.ds.*; 7 | using Lambda; 8 | using StringTools; 9 | 10 | #if macro 11 | /** 12 | Compile-time configuration of jQuery. 13 | **/ 14 | @:noPackageRestrict 15 | @:allow(js.jquery) 16 | class Config { 17 | static var plugins(default, null):Map> = new Map(); 18 | static var isBuilt(default, null):Bool = false; 19 | static var defaultVersion(default, null) = '30600'; // assume to be latest supported version 20 | 21 | static public function init():Void { 22 | var jquery_ver = haxe.macro.Context.definedValue("jquery_ver"); 23 | if (jquery_ver == null) { 24 | haxe.macro.Compiler.define("jquery_ver", defaultVersion); 25 | } 26 | } 27 | 28 | /** 29 | Add an Plugin extern class. All fields of the class will be injected into JQuery/JQueryStatic. 30 | **/ 31 | static public function addPlugin(pluginFullName:String):Void { 32 | //indicate that the Plugin is added by calling this function 33 | plugins.set(pluginFullName, null); 34 | 35 | //force building the Plugin 36 | var ct = Context.toComplexType(Context.getType(pluginFullName)); 37 | Context.typeof(macro {var v:$ct = null; v;}); 38 | } 39 | 40 | /** 41 | Will be set as the value of @:native on JQuery and JQueryStatic. 42 | Can be "$" or "jQuery". Default to "$". Other values need to be handled manually. 43 | **/ 44 | static public var native(default, null):String = "$"; 45 | 46 | /** 47 | Setter of Config.native. 48 | Used in hxml: --macro js.jquery.Config.setNative('jQuery') 49 | **/ 50 | static public function setNative(v:String):String { 51 | return native = v; 52 | } 53 | 54 | /** 55 | jQuery version to be used. Encoded as dot-format, e.g. "1.12.4". 56 | Default is the version supported by Haxe 3 std lib, or the version this extern is generated for. 57 | **/ 58 | static public var version(get, never):String; 59 | static function get_version():String { 60 | var jquery_ver = haxe.macro.Context.definedValue("jquery_ver"); 61 | if (jquery_ver == null) { 62 | throw "Missing compiler define jquery_ver. If not using -lib jQueryExtern, try add --macro js.jquery.Config.init()."; 63 | } 64 | return Utils.parseIntVersion(Std.parseInt(jquery_ver)).join("."); 65 | } 66 | 67 | /** 68 | Setter of Config.version. 69 | Used in hxml: --macro js.jquery.Config.setVersion("1.8.3") 70 | **/ 71 | static public function setVersion(v:String):String { 72 | var ver = Utils.versionToInt(v.split(".").map(Std.parseInt)); 73 | haxe.macro.Compiler.define("jquery_ver", Std.string(ver)); 74 | return v; 75 | } 76 | 77 | /** 78 | Define if deprecated jQuery APIs are allowed or not. 79 | **/ 80 | static public var allowDeprecated(default, null):Bool = true; 81 | 82 | /** 83 | Setter of Config.allowDeprecated. 84 | Used in hxml: --macro js.jquery.Config.setAllowDeprecated(true) 85 | **/ 86 | static public function setAllowDeprecated(v:Bool):Bool { 87 | return allowDeprecated = v; 88 | } 89 | 90 | /** 91 | Build function of all generated extern. 92 | Used for injecting plugin extern and setting @:native. 93 | **/ 94 | static public function build():Array { 95 | var fields = Context.getBuildFields(); 96 | var clsType = Context.getLocalClass().get(); 97 | 98 | // add @:native 99 | switch (clsType.name) { 100 | case "JQuery": 101 | if(Context.defined('hxnodejs')) clsType.meta.add(":jsRequire", [macro "jquery"], clsType.pos); 102 | else clsType.meta.add(":native", [macro $v{native}], clsType.pos); 103 | 104 | for (plugin in plugins) { 105 | for (field in plugin) { 106 | fields.push(field); 107 | } 108 | } 109 | default: 110 | if(Context.defined('hxnodejs')) { 111 | clsType.meta.add(":jsRequire", [macro "jquery", macro $v{clsType.name}], clsType.pos); 112 | } else { 113 | var native = native + "." + clsType.name; 114 | clsType.meta.add(":native", [macro $v{native}], clsType.pos); 115 | } 116 | } 117 | 118 | // filter and group the fields 119 | var ver = Utils.parseStringVersion(version); 120 | var instanceFieldMap = new Map>(); 121 | var staticFieldMap = new Map>(); 122 | for (field in fields) { 123 | // filtering based on @:jQueryVersion 124 | var jQueryVersionMeta = field.meta.filter(function(m) return m.name == ":jQueryVersion")[0]; 125 | if (jQueryVersionMeta != null) { 126 | var jQueryVersionMetaVal = jQueryVersionMeta.params[0]; 127 | if (jQueryVersionMetaVal != null) { 128 | switch (jQueryVersionMetaVal.expr) { 129 | case EObjectDecl(fields): 130 | if (fields.exists(function(f):Bool { 131 | return switch(f) { 132 | case { field: "added", expr: {expr: EConst(CString(val)), pos:_} }: 133 | if (val.indexOf("/") != -1) 134 | val = val.split("/")[0]; 135 | if (val.indexOf("-and-") != -1) 136 | val = val.split("-and-")[0]; 137 | Utils.compareVersion(ver, Utils.parseStringVersion(val)) < 0; 138 | case { field: "deprecated", expr: {expr: EConst(CString(val)), pos:_} }: 139 | !allowDeprecated && Utils.compareVersion(ver, Utils.parseStringVersion(val)) >= 0; 140 | case { field: "removed", expr: {expr: EConst(CString(val)), pos:_} }: 141 | Utils.compareVersion(ver, Utils.parseStringVersion(val)) >= 0; 142 | default: 143 | throw 'Invalid field of @:jQueryVersion: ${f.field}: ${f.expr}'; 144 | } 145 | })) continue; 146 | default: 147 | throw "Param of @:jQueryVersion should be EObjectDecl."; 148 | } 149 | } 150 | } 151 | 152 | // valid field, add to fieldMap 153 | var fieldMap = if (field.access.has(AStatic)) 154 | staticFieldMap; 155 | else 156 | instanceFieldMap; 157 | 158 | if (!fieldMap.exists(field.name)) { 159 | fieldMap.set(field.name, new Array()); 160 | } 161 | fieldMap.get(field.name).push(field); 162 | } 163 | 164 | // return new fields with @:overload aggregated 165 | var newFields = []; 166 | for (fieldMap in [staticFieldMap, instanceFieldMap]) 167 | for (fields in fieldMap) { 168 | var field = fields.shift(); 169 | field.meta = [ 170 | for (m in field.meta) 171 | if (![":overload", ":jQueryVersion"].has(m.name)) 172 | m 173 | ]; 174 | 175 | var docMap = new Map(); 176 | if (field.doc != null) 177 | docMap.set(field.doc, null); 178 | 179 | for (overloadField in fields) { 180 | var func:Function = switch(overloadField.kind) { 181 | case FFun(f): f; 182 | default: throw "Should only overload a function."; 183 | } 184 | func.expr = macro {}; 185 | field.meta.push({ 186 | name: ":overload", 187 | params: [{ expr: EFunction(null, func), pos: overloadField.pos }], 188 | pos: overloadField.pos 189 | }); 190 | 191 | if (overloadField.doc != null && !docMap.exists(overloadField.doc)) { 192 | field.doc = (field.doc == null ? "" : field.doc + "\n OR: ") + overloadField.doc; 193 | docMap.set(overloadField.doc, null); 194 | } 195 | } 196 | newFields.push(field); 197 | } 198 | 199 | isBuilt = true; 200 | return newFields; 201 | } 202 | } 203 | #end 204 | -------------------------------------------------------------------------------- /js/jquery/Deferred.hx: -------------------------------------------------------------------------------- 1 | /* This file is generated, do not edit! Visit https://api.jquery.com/ for API documentation. */ 2 | package js.jquery; 3 | @:build(js.jquery.Config.build()) extern class Deferred { 4 | /** 5 | Add handlers to be called when the Deferred object is either resolved or rejected. 6 | **/ 7 | @:jQueryVersion({ added : "1.6" }) 8 | public function always(alwaysCallbacks:haxe.extern.EitherType>, ?alwaysCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; 9 | /** 10 | Add handlers to be called when the Deferred object is rejected. 11 | **/ 12 | @:native("catch") 13 | @:jQueryVersion({ added : "3.0" }) 14 | public function _catch(failFilter:haxe.Constraints.Function):js.jquery.Promise; 15 | /** 16 | Add handlers to be called when the Deferred object is resolved. 17 | **/ 18 | @:jQueryVersion({ added : "1.5" }) 19 | public function done(doneCallbacks:haxe.extern.EitherType>, ?doneCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; 20 | /** 21 | Add handlers to be called when the Deferred object is rejected. 22 | **/ 23 | @:jQueryVersion({ added : "1.5" }) 24 | public function fail(failCallbacks:haxe.extern.EitherType>, ?failCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; 25 | /** 26 | Determine whether a Deferred object has been rejected. 27 | **/ 28 | @:jQueryVersion({ added : "1.5", deprecated : "1.7", removed : "1.8" }) 29 | public function isRejected():Bool; 30 | /** 31 | Determine whether a Deferred object has been resolved. 32 | **/ 33 | @:jQueryVersion({ added : "1.5", deprecated : "1.7", removed : "1.8" }) 34 | public function isResolved():Bool; 35 | /** 36 | A factory function that returns a chainable utility object with methods to register multiple callbacks into callback queues, invoke callback queues, and relay the success or failure state of any synchronous or asynchronous function. 37 | **/ 38 | @:selfCall 39 | @:jQueryVersion({ added : "1.5" }) 40 | public function new(?beforeStart:js.jquery.Deferred -> Void):Void; 41 | /** 42 | Call the progressCallbacks on a Deferred object with the given args. 43 | **/ 44 | @:jQueryVersion({ added : "1.7" }) 45 | public function notify(args:Dynamic):js.jquery.Deferred; 46 | /** 47 | Call the progressCallbacks on a Deferred object with the given context and args. 48 | **/ 49 | @:jQueryVersion({ added : "1.7" }) 50 | public function notifyWith(context:Dynamic, ?args:Array):js.jquery.Deferred; 51 | /** 52 | Utility method to filter and/or chain Deferreds. 53 | **/ 54 | @:overload 55 | @:jQueryVersion({ added : "1.6", deprecated : "1.8" }) 56 | public function pipe(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function):js.jquery.Promise; 57 | /** 58 | Utility method to filter and/or chain Deferreds. 59 | **/ 60 | @:overload 61 | @:jQueryVersion({ added : "1.7", deprecated : "1.8" }) 62 | public function pipe(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise; 63 | /** 64 | Add handlers to be called when the Deferred object generates progress notifications. 65 | **/ 66 | @:jQueryVersion({ added : "1.7" }) 67 | public function progress(progressCallbacks:haxe.extern.EitherType, Array>>, ?progressCallbacks:haxe.extern.EitherType, Array>>):js.jquery.Deferred; 68 | /** 69 | Return a Deferred's Promise object. 70 | **/ 71 | @:jQueryVersion({ added : "1.5" }) 72 | public function promise(?target:Dynamic):js.jquery.Promise; 73 | /** 74 | Reject a Deferred object and call any failCallbacks with the given args. 75 | **/ 76 | @:jQueryVersion({ added : "1.5" }) 77 | public function reject(?args:Dynamic):js.jquery.Deferred; 78 | /** 79 | Reject a Deferred object and call any failCallbacks with the given context and args. 80 | **/ 81 | @:jQueryVersion({ added : "1.5" }) 82 | public function rejectWith(context:Dynamic, ?args:Array):js.jquery.Deferred; 83 | /** 84 | Resolve a Deferred object and call any doneCallbacks with the given args. 85 | **/ 86 | @:jQueryVersion({ added : "1.5" }) 87 | public function resolve(?args:Dynamic):js.jquery.Deferred; 88 | /** 89 | Resolve a Deferred object and call any doneCallbacks with the given context and args. 90 | **/ 91 | @:jQueryVersion({ added : "1.5" }) 92 | public function resolveWith(context:Dynamic, ?args:Array):js.jquery.Deferred; 93 | /** 94 | Determine the current state of a Deferred object. 95 | **/ 96 | @:jQueryVersion({ added : "1.7" }) 97 | public function state():String; 98 | /** 99 | Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. 100 | **/ 101 | @:overload 102 | @:jQueryVersion({ added : "1.5", removed : "1.8" }) 103 | public function then(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>):js.jquery.Promise; 104 | /** 105 | Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. 106 | **/ 107 | @:overload 108 | @:jQueryVersion({ added : "1.8" }) 109 | public function then(doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise; 110 | /** 111 | Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. 112 | **/ 113 | @:overload 114 | @:jQueryVersion({ added : "1.7", removed : "1.8" }) 115 | public function then(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>, ?progressCallbacks:haxe.extern.EitherType>):js.jquery.Promise; 116 | } -------------------------------------------------------------------------------- /js/jquery/Error.hx: -------------------------------------------------------------------------------- 1 | package js.jquery; 2 | 3 | #if (haxe_ver >= 4) 4 | typedef Error = js.lib.Error; 5 | #else 6 | typedef Error = js.Error; 7 | #end -------------------------------------------------------------------------------- /js/jquery/Event.hx: -------------------------------------------------------------------------------- 1 | /* This file is generated, do not edit! Visit https://api.jquery.com/ for API documentation. */ 2 | package js.jquery; 3 | @:build(js.jquery.Config.build()) extern class Event extends js.html.Event { 4 | /** 5 | An optional object of data passed to an event method when the current executing handler is bound. 6 | **/ 7 | @:jQueryVersion({ added : "1.1" }) 8 | public var data : Dynamic; 9 | /** 10 | The element where the currently-called jQuery event handler was attached. 11 | **/ 12 | @:jQueryVersion({ added : "1.7" }) 13 | public var delegateTarget : js.html.Element; 14 | /** 15 | Returns whether event.preventDefault() was ever called on this event object. 16 | **/ 17 | @:jQueryVersion({ added : "1.3" }) 18 | public function isDefaultPrevented():Bool; 19 | /** 20 | Returns whether event.stopImmediatePropagation() was ever called on this event object. 21 | **/ 22 | @:jQueryVersion({ added : "1.3" }) 23 | public function isImmediatePropagationStopped():Bool; 24 | /** 25 | Returns whether event.stopPropagation() was ever called on this event object. 26 | **/ 27 | @:jQueryVersion({ added : "1.3" }) 28 | public function isPropagationStopped():Bool; 29 | /** 30 | Indicates whether the META key was pressed when the event fired. 31 | **/ 32 | @:jQueryVersion({ added : "1.0.4" }) 33 | public var metaKey : Bool; 34 | /** 35 | The namespace specified when the event was triggered. 36 | **/ 37 | @:jQueryVersion({ added : "1.4.3" }) 38 | public var namespace : String; 39 | /** 40 | The mouse position relative to the left edge of the document. 41 | **/ 42 | @:jQueryVersion({ added : "1.0.4" }) 43 | public var pageX : Float; 44 | /** 45 | The mouse position relative to the top edge of the document. 46 | **/ 47 | @:jQueryVersion({ added : "1.0.4" }) 48 | public var pageY : Float; 49 | /** 50 | The other DOM element involved in the event, if any. 51 | **/ 52 | @:jQueryVersion({ added : "1.1.4" }) 53 | public var relatedTarget : js.html.Element; 54 | /** 55 | The last value returned by an event handler that was triggered by this event, unless the value was undefined. 56 | **/ 57 | @:jQueryVersion({ added : "1.3" }) 58 | public var result : Dynamic; 59 | /** 60 | For key or mouse events, this property indicates the specific key or button that was pressed. 61 | **/ 62 | @:jQueryVersion({ added : "1.1.3" }) 63 | public var which : Float; 64 | /** 65 | 66 | Returns a `Boolean` that is `true` if the Alt ( Option or ⌥ on OS X) key was active when the key event was generated. 67 | 68 | **/ 69 | public var altKey : Bool; 70 | /** 71 | 72 | The button number that was pressed when the mouse event was fired.  73 | 74 | **/ 75 | public var button : Int; 76 | /** 77 | 78 | 79 | The buttons being pressed when the mouse event was fired 80 | 81 | 82 | **/ 83 | public var buttons : Int; 84 | public var char : Int; 85 | /** 86 | 87 | Returns a `Number` representing the Unicode reference number of the key; this attribute is used only by the `keypress` event. For keys whose `char` attribute contains multiple characters, this is the Unicode value of the first character in that attribute. In Firefox 26 this returns codes for printable characters. 88 | Warning: This attribute is deprecated; you should use `KeyboardEvent.key` instead, if available. 89 | 90 | 91 | **/ 92 | public var charCode : Int; 93 | /** 94 | 95 | The X coordinate of the mouse pointer in local (DOM content) coordinates. 96 | 97 | **/ 98 | public var clientX : Int; 99 | /** 100 | 101 | The Y coordinate of the mouse pointer in local (DOM content) coordinates. 102 | 103 | **/ 104 | public var clientY : Int; 105 | /** 106 | 107 | Returns a `Boolean` that is `true` if the Ctrl key was active when the key event was generated. 108 | 109 | **/ 110 | public var ctrlKey : Bool; 111 | /** 112 | 113 | Returns a `long` with details about the event, depending on the event type. 114 | 115 | **/ 116 | public var detail : Int; 117 | /** 118 | 119 | Returns a `DOMString` representing the key value of the key represented by the event. 120 | 121 | **/ 122 | public var key : String; 123 | /** 124 | 125 | Returns a `Number` representing a system and implementation dependent numerical code identifying the unmodified value of the pressed key. 126 | Warning: This attribute is deprecated; you should use `KeyboardEvent.key` instead, if available. 127 | 128 | 129 | **/ 130 | public var keyCode : Int; 131 | public var offsetX : Int; 132 | public var offsetY : Int; 133 | /** 134 | 135 | The X coordinate of the mouse pointer in global (screen) coordinates. 136 | 137 | **/ 138 | public var screenX : Int; 139 | /** 140 | 141 | The Y coordinate of the mouse pointer in global (screen) coordinates. 142 | 143 | **/ 144 | public var screenY : Int; 145 | /** 146 | 147 | Returns a `Boolean` that is `true` if the Shift key was active when the key event was generated. 148 | 149 | **/ 150 | public var shiftKey : Bool; 151 | public var toElement : js.html.Element; 152 | /** 153 | 154 | Returns a `WindowProxy` that contains the view that generated the event. 155 | 156 | **/ 157 | public var view : js.html.Window; 158 | /** 159 | A convenient method of getting `$(this)`, which is typically the same as `$(evt.currentTarget)`. 160 | For detail, refer to https://api.jquery.com/event.currenttarget/. 161 | **/ 162 | inline public function getThis():js.jquery.JQuery return new js.jquery.JQuery(js.Lib.nativeThis); 163 | } -------------------------------------------------------------------------------- /js/jquery/ExternGenerator.hx: -------------------------------------------------------------------------------- 1 | package js.jquery; 2 | 3 | import sys.*; 4 | import sys.io.*; 5 | import haxe.xml.*; 6 | import haxe.macro.*; 7 | import haxe.macro.Expr; 8 | import mcli.*; 9 | import haxe.ds.*; 10 | using haxe.macro.ComplexTypeTools; 11 | using StringTools; 12 | using Lambda; 13 | using Reflect; 14 | 15 | @:noPackageRestrict 16 | typedef FuncConfig = { ?doc:String, ?added:String, ?deprecated:String, ?removed:String } 17 | 18 | #if (haxe_ver >= 4) 19 | typedef Fast = haxe.xml.Access 20 | #end 21 | 22 | /** 23 | Generates extern classes. 24 | */ 25 | @:noPackageRestrict 26 | class ExternGenerator #if (mcli && !macro) extends CommandLine #end { 27 | /** 28 | Haxe keywords. Used to rename api function/variables names. 29 | **/ 30 | static var keywords(default, null) = ["function", "true", "false", "if", "else", "switch", "class", "interface"]; 31 | 32 | /** 33 | The package that stores the output classes. 34 | */ 35 | public var pack(default, null):String = "jQuery"; 36 | 37 | /** 38 | The path to api.xml. 39 | You can get the latest one from https://api.jquery.com/resources/api.xml. 40 | */ 41 | public var apiXml(default, null):String = "api.xml"; 42 | 43 | /** 44 | The output folder. 45 | */ 46 | public var outputFolder(default, null):String = "."; 47 | 48 | /** 49 | The value of @:native. 50 | */ 51 | public var native(default, null):String = "$"; 52 | 53 | /** 54 | Whether allow the use of build macros for advanced config. 55 | */ 56 | public var noBuild(default, null):Bool = false; 57 | 58 | /** 59 | Use `js.html.Element` or `js.html.Node` as type param constraint. 60 | */ 61 | public var useElement(default, null):Bool = false; 62 | 63 | /** 64 | Use `haxe.extern.EitherType`. 65 | */ 66 | public var useHaxeEither(default, null):Bool = false; 67 | 68 | /** 69 | Use `haxe.extern.Rest`. 70 | */ 71 | public var useHaxeRest(default, null):Bool = false; 72 | 73 | /** 74 | Put all fields, including the static ones, into a single JQuery class. 75 | */ 76 | public var noSeperatedStatic(default, null):Bool = false; 77 | 78 | /** 79 | Rename field names that are shared between static/instance. 80 | */ 81 | public var noRenameStaticField(default, null):Bool = false; 82 | 83 | /** 84 | Add haxe iterator. 85 | */ 86 | public var addHaxeIterator(default, null):Bool = false; 87 | 88 | /** 89 | https://api.jquery.com/category/events/event-object/ 90 | https://github.com/jquery/jquery/blob/master/src/event.js 91 | https://github.com/jquery/api.jquery.com/blob/master/categories.xml#L146 92 | */ 93 | var coreEventFields(default, never):Array<{ 94 | name:String, 95 | type:ComplexType, 96 | kind:haxe.macro.Type.FieldKind, 97 | doc:Null, 98 | }> = [] 99 | .concat(getFields("js.html.Event")) 100 | .concat(getFields("js.html.UIEvent")) 101 | .concat(getFields("js.html.KeyboardEvent")) 102 | .concat(getFields("js.html.MouseEvent")) 103 | ; 104 | var copiedEventFields(default, never):Array = "altKey, bubbles, button, buttons, cancelable, char, charCode, clientX, clientY, ctrlKey, currentTarget, data, detail, eventPhase, key, keyCode, metaKey, offsetX, offsetY, originalTarget, pageX, pageY, relatedTarget, screenX, screenY, shiftKey, target, toElement, view, which".split(", "); 105 | 106 | var api:Fast; 107 | 108 | function eitherTypes(e:ComplexType):Map { 109 | var ePath = if (useHaxeEither) { 110 | { 111 | pack: ["haxe", "extern"], 112 | name: "EitherType" 113 | }; 114 | } else { 115 | { 116 | pack: pack.split(".").concat(["haxe"]), 117 | name: "Either" 118 | }; 119 | } 120 | return switch (e) { 121 | case TPath(tp) if (tp.pack.join(".") == ePath.pack.join(".") && tp.name == ePath.name): 122 | var m = new Map(); 123 | for (p in tp.params) switch (p) { 124 | case TPType(t): 125 | var ts = eitherTypes(t); 126 | for (k in ts.keys()) 127 | m[k] = ts[k]; 128 | case _: throw "should be TPType"; 129 | }; 130 | m; 131 | case _: [e.toString() => e]; 132 | } 133 | } 134 | 135 | function either(types:Array):ComplexType { 136 | var typeMap = types.map(eitherTypes).fold(function(m:Map, all:Map) { 137 | for (k in m.keys()) 138 | all[k] = m[k]; 139 | return all; 140 | }, new Map()); 141 | if (typeMap.exists("Dynamic")) 142 | typeMap = ["Dynamic" => macro:Dynamic]; 143 | types = [for (t in typeMap) t]; 144 | types.sort(compareComplexType); 145 | 146 | function _either(types:Array):ComplexType { 147 | return switch (types.length) { 148 | case 0: 149 | throw types; 150 | case 1: 151 | types[0]; 152 | case len: 153 | if (useHaxeEither) { 154 | TPath({ 155 | pack: ["haxe", "extern"], 156 | name: "EitherType", 157 | params: [TPType(types[0]), TPType(either(types.slice(1)))] 158 | }); 159 | } else { 160 | TPath({ 161 | pack: pack.split(".").concat(["haxe"]), 162 | name: "Either", 163 | params: [TPType(types[0]), TPType(either(types.slice(1)))] 164 | }); 165 | } 166 | } 167 | } 168 | return _either(types); 169 | } 170 | 171 | function jqType(name:String, ?params:Array):ComplexType { 172 | return TPath({ 173 | pack: pack.split("."), 174 | name: name, 175 | params: params 176 | }); 177 | } 178 | 179 | function rest(type:ComplexType):ComplexType { 180 | return if (useHaxeRest) 181 | TPath({ 182 | pack: ["haxe", "extern"], 183 | name: "Rest", 184 | params: [TPType(type)] 185 | }); 186 | else 187 | TPath({ 188 | pack: pack.split(".").concat(["haxe"]), 189 | name: "Rest", 190 | params: [TPType(type)] 191 | }); 192 | } 193 | 194 | var element(get, never):ComplexType; 195 | function get_element():ComplexType { 196 | return if (useElement) { 197 | macro:js.html.Element; 198 | } else { 199 | macro:js.html.Node; 200 | } 201 | } 202 | 203 | function toFunctionComplexType(tag:Fast):ComplexType { 204 | var args = [for (a in tag.nodes.argument) either(toComplexType(a.att.type, a))]; 205 | var rets = if (tag.hasNode.resolve("return")) { 206 | var retNode = tag.node.resolve("return"); 207 | if (retNode.has.type) 208 | toComplexType(retNode.att.type) 209 | else if (retNode.hasNode.type) 210 | [ 211 | for (c in retNode.nodes.type.fold( 212 | function(t, map:Map) { 213 | for (c in toComplexType(t.att.name)) 214 | map[c] = true; 215 | return map; 216 | }, 217 | new Map() 218 | ).keys()) 219 | c 220 | ]; 221 | else 222 | throw "no type for return?"; 223 | } else null; 224 | 225 | var ct = if (rets == null && args.length == 0) 226 | macro:haxe.Constraints.Function 227 | else { 228 | TFunction( 229 | args, 230 | either(rets == null ? [macro:Void] : rets) 231 | ); 232 | } 233 | 234 | switch (ct) { 235 | case TFunction(args, ret): 236 | var lastArg = args[args.length-1]; 237 | switch (lastArg) { 238 | case null: 239 | //pass 240 | case TPath({ 241 | pack: p, 242 | name: "Rest", 243 | params: [restType] 244 | }) if (p.join(".") == '${pack}.haxe'): 245 | ct = either([ 246 | TFunction(args.slice(0, args.length-1), ret), 247 | ct, 248 | ]); 249 | case _: 250 | //pass 251 | } 252 | case macro:haxe.Constraints.Function: 253 | //pass 254 | case _: 255 | throw "unknown function type"; 256 | } 257 | 258 | if (tag.att.name.toLowerCase().endsWith("callbacks")){ 259 | ct = either([ct, macro:Array<$ct>]); 260 | } 261 | 262 | return ct; 263 | } 264 | 265 | /** 266 | Find the entry node, recurse to the parent. 267 | */ 268 | static function getEntryName(tag:Xml):String { 269 | return switch (tag.nodeName) { 270 | case "entry": tag.get("name"); 271 | case _: getEntryName(tag.parent); 272 | } 273 | } 274 | 275 | /** 276 | Maps a type in api.xml to one or more Haxe ComplexType. 277 | tag is the xml node where the type is listed. 278 | **/ 279 | function toComplexType(type:String, ?tag:Fast, ?inRest = false):Array { 280 | var tagName = tag == null ? "" : tag.att.name; 281 | var entryName = tag == null ? "" : getEntryName(tag.x); 282 | if (type != null) type = type.trim(); 283 | 284 | if (!inRest && tag != null && tag.has.rest && tag.att.rest == "true") { 285 | return toComplexType(type, tag, true) 286 | .map(rest); 287 | } 288 | 289 | var simple = type == null ? [macro:Dynamic] : switch(type) { 290 | case "jQueryStatic": 291 | [jqType("JQueryStatic")]; 292 | case "jQuery", "jQuery object": 293 | [jqType("JQuery")]; 294 | case "event", "Event": 295 | [jqType("Event")]; 296 | case "callbacks", "Callbacks": 297 | [jqType("Callbacks")]; 298 | case "Promise": 299 | [jqType("Promise")]; 300 | case "Thenable": 301 | [macro:js.jquery.Thenable]; 302 | case "jqXHR": 303 | [jqType("JqXHR")]; 304 | case "Selector", "selector": 305 | [macro:String]; 306 | case "htmlString", "HTML": 307 | [macro:String]; 308 | case "document", "XMLDocument": 309 | [macro:js.html.Document]; 310 | case "Element": 311 | [element]; 312 | /*case "Elements": 313 | [macro:Array<$element>];*/ 314 | 315 | case "Error": 316 | [macro:js.jquery.Error]; 317 | 318 | case "Boolean", "boolean": 319 | [macro:Bool]; 320 | case "Number": 321 | [macro:Float]; 322 | case "Integer": 323 | [macro:Int]; 324 | case "String" | "Text": 325 | [macro:String]; 326 | case "Anything": 327 | [macro:Dynamic]; 328 | case ("Object" | "PlainObject") if (!["offset", "position"].has(entryName) && !["jQuery object"].has(tagName)): 329 | [macro:Dynamic]; //should be {}, but jQuery doc uses "Object" for "Anything" :( 330 | case "ArrayLikeObject": 331 | [macro:Array, macro:js.html.NodeList]; 332 | case "undefined", "": 333 | [macro:Void]; 334 | 335 | case "Function": 336 | [toFunctionComplexType(tag)]; 337 | 338 | case "Null": 339 | []; 340 | 341 | case _ if (type.indexOf(",") >= 0): 342 | //older version of api.xml sometimes use , to list multiple types... 343 | trace(type); 344 | type.split(",") 345 | .map(toComplexType.bind(_, tag)) 346 | .fold(function(ts,all:Array) return all.concat(ts), []); 347 | 348 | default: 349 | null; 350 | } 351 | 352 | return simple != null ? simple : switch ([entryName, tagName, type]) { 353 | case ["jQuery.globalEval", "doc", "Document"]: 354 | [macro:js.html.Document]; 355 | case ["jQuery.each", "array", "Array"]: 356 | [macro:Array]; 357 | case ["jQuery.parseHTML", "jQuery.parseHTML", "Array"]: 358 | [macro:Array<$element>]; 359 | case ["jQuery.parseJSON", "jQuery.parseJSON", "Array"]: 360 | [macro:Array]; 361 | case ["add", "elements", "Elements"]: 362 | [element, macro:js.html.NodeList]; 363 | case ["addClass" | "removeClass" | "toggleClass", "classNames", "Array"]: 364 | [macro:Array]; 365 | case ["appendTo" | "insertBefore" | "replaceAll" | "prependTo" | "insertAfter", "target", "Array"]: 366 | [macro:Array<$element>]; 367 | case ["css", "propertyNames", "Array"]: 368 | [macro:Array]; 369 | case ["jQuery.queue", "jQuery.queue" | "newQueue", "Array"]: 370 | [macro:ArrayVoid>]; 371 | case ["queue", "queue" | "newQueue", "Array"]: 372 | [macro:ArrayVoid>]; 373 | case ["serializeArray", "serializeArray", "Array"]: 374 | [macro:Array]; 375 | case ["triggerHandler", "extraParameters", "Array"]: 376 | [macro:Array]; 377 | case ["replaceWith", "newContent", "Array"]: 378 | [macro:Array<$element>]; 379 | case ["pushStack", "elements", "Array"]: 380 | [macro:Array<$element>, macro:js.html.NodeList]; 381 | case ["pushStack", "arguments", "Array"]: 382 | [macro:Array]; 383 | case ["not", "selector", "Array"]: 384 | [macro:Array<$element>]; 385 | case ["val", "value", "Array"]: 386 | [macro:Array]; 387 | case ["val", "val", "Array"]: 388 | [macro:Array]; 389 | case ["closest", "selectors", "Array"]: 390 | [macro:String, macro:Array, jqType("JQuery")]; 391 | case ["closest", "closest", "Array"]: 392 | [macro:Array]; 393 | case ["jQuery", "elementArray", "Array"]: 394 | [macro:js.html.NodeList, macro:Array<$element>]; 395 | case ["jQuery", "ownerDocument", "Document"]: 396 | [macro:js.html.Document]; 397 | case ["toArray", "toArray", "Array"]: 398 | [macro:Array<$element>]; 399 | case ["jQuery.inArray", "array", "Array"]: 400 | [macro:Array]; 401 | case ["jQuery.makeArray", "jQuery.makeArray", "Array"]: 402 | [macro:Array]; 403 | case ["jQuery.map", "jQuery.map", "Array"]: 404 | [macro:Array]; 405 | case ["jQuery.map", "array", "Array"]: 406 | [macro:Array]; 407 | case ["jQuery.map", "arrayOrObject", "Array"]: 408 | [macro:Array, macro:{}]; 409 | case ["jQuery.grep", _, "Array"]: 410 | [macro:Array]; 411 | case ["jQuery.merge", _, "Array"]: 412 | [macro:Array]; 413 | case ["trigger", "extraParameters", "Array"]: 414 | [macro:Array]; 415 | case ["removeData", "list", "Array"]: 416 | [macro:Array]; 417 | case ["jQuery.param", "obj", "Array"]: 418 | [macro:Array]; 419 | 420 | case ["callbacks.add"|"callbacks.remove", "callbacks", "Array"]: 421 | []; 422 | 423 | case [_, "content", "Array"]: 424 | var jq = jqType("JQuery"); 425 | [macro:Array<$element>, macro:js.html.NodeList, macro:Array, macro:Array<$jq>]; 426 | 427 | case [_, "jQuery object", _]: 428 | [jqType("JQuery")]; 429 | 430 | case ["offset" | "position", _, "Object" | "PlainObject"]: 431 | [macro:{top:Float, left:Float}]; 432 | 433 | case [ 434 | _, 435 | "doneCallbacks" | "failCallbacks" | "progressCallbacks" | "alwaysCallbacks", 436 | "Array" 437 | ]: 438 | [macro:Array]; 439 | 440 | case [ 441 | "deferred.resolveWith" | "deferred.rejectWith" | "deferred.notifyWith", 442 | "args", 443 | "Array" 444 | ]: 445 | [macro:Array]; 446 | 447 | case ["jQuery.unique" | "jQuery.uniqueSort", _, "Array"]: 448 | [macro:Array<$element>]; 449 | 450 | case ["get", "get", "Array"]: 451 | [macro:Array<$element>]; 452 | 453 | case [_, "deferreds", "Deferred"|"deferred"]: 454 | [rest(jqType("Deferred"))]; 455 | 456 | case [_, _, "Deferred"|"deferred"]: 457 | [jqType("Deferred")]; 458 | 459 | default: 460 | trace('["${entryName}", "${tagName}", "${type}"]'); 461 | [macro:Dynamic]; 462 | } 463 | } 464 | 465 | /** 466 | Compare function for Array.sort(). 467 | Stricter ComplexType will come first (returns -ve); more dynamic one will come last (returns +ve). 468 | **/ 469 | static public function compareComplexType(a:ComplexType, b:ComplexType):Int { 470 | return 471 | switch ([a, b]) { 472 | case [macro:Dynamic, macro:Dynamic]: 473 | 0; 474 | case [macro:Dynamic, TPath({pack:[], name:"Dynamic", params:_})]: 475 | 1; 476 | case [TPath({pack:[], name:"Dynamic", params:_}), macro:Dynamic]: 477 | -1; 478 | case [TPath({pack:[], name:"Dynamic", params:[TPType(paramA)]}), TPath({pack:[], name:"Dynamic", params:[TPType(paramB)]})]: 479 | compareComplexType(paramA, paramB); 480 | 481 | case [TPath({pack:[], name:"Dynamic", params:_}), _]: 482 | 1; 483 | case [_, TPath({pack:[], name:"Dynamic", params:_})]: 484 | -1; 485 | 486 | case [TPath({name:"Either", params:_}), _]: 487 | 1; 488 | case [_, TPath({name:"Either", params:_})]: 489 | -1; 490 | 491 | case [macro:Float, macro:Int]: 492 | 1; 493 | case [macro:Int, macro:Float]: 494 | -1; 495 | 496 | case [TPath(tpA), TPath(tpB)] if (tpA.name == tpB.name && tpA.pack.join(".") == tpB.pack.join(".")): 497 | var pdiff = tpA.params.length - tpB.params.length; 498 | if (pdiff != 0) { 499 | pdiff; 500 | } else { 501 | Reflect.compare(tpA.name, tpB.name); 502 | } 503 | 504 | case [_, TPath(_)]: 505 | 1; 506 | case [TPath(_), _]: 507 | -1; 508 | 509 | case [TAnonymous(fieldsA), TAnonymous(fieldsB)]: 510 | fieldsB.length - fieldsA.length; 511 | case [TExtend(_, fieldsA), TExtend(_, fieldsB)]: 512 | fieldsB.length - fieldsA.length; 513 | 514 | case _: 515 | 0; 516 | } 517 | } 518 | 519 | /** 520 | Compare function for Array.sort(). 521 | Function with stricter arguments will come first (returns -ve); more dynamic one will come last (returns +ve). 522 | **/ 523 | static public function compareFunctions(a:Function, b:Function):Int { 524 | if (a.args.length != b.args.length) { 525 | return a.args.length - b.args.length; 526 | } else { 527 | for (i in 0...a.args.length) { 528 | var aArg = a.args[i], bArg = b.args[i]; 529 | switch([aArg, bArg]) { 530 | case [{opt:true}, {opt:false}]: 531 | return 1; 532 | case [{opt:false}, {opt:true}]: 533 | return -1; 534 | case _: 535 | var v = compareComplexType(aArg.type, bArg.type); 536 | if (v != 0) 537 | return v; 538 | } 539 | } 540 | return 0; 541 | } 542 | } 543 | 544 | macro static public function funcSig(e:Expr):ExprOf { 545 | switch(e.expr) { 546 | case EFunction(_, f): 547 | return macro { 548 | params: $v{f.params}, 549 | args: $v{[for (a in f.args) {opt: a.opt, name: a.name, type: a.type, value: a.value}]}, 550 | ret: $v{f.ret}, 551 | expr: null 552 | }; 553 | default: 554 | return throw "Input is not EFunction."; 555 | } 556 | } 557 | 558 | static public function infoFromName(field:String):{ 559 | owner:String, 560 | field:String, 561 | sub:Array, 562 | isStatic:Bool 563 | } { 564 | if (field == "jQuery") { 565 | return { 566 | owner: "jQuery", 567 | field: "new", 568 | sub: [], 569 | isStatic: false 570 | } 571 | } 572 | var names = field.split("."); 573 | var isJQueryStatic = names[0] == "jQuery"; 574 | if (isJQueryStatic) { 575 | names.shift(); 576 | } 577 | if (isJQueryStatic || names.length == 1) { 578 | return { 579 | owner: "jQuery", 580 | field: names[0], 581 | sub: names.slice(1), 582 | isStatic: isJQueryStatic 583 | } 584 | } else { 585 | var owner = names.shift(); 586 | return { 587 | owner: owner, 588 | field: names[0], 589 | sub: names.slice(1), 590 | isStatic: false 591 | } 592 | } 593 | } 594 | 595 | function generate():Array { 596 | var out = []; 597 | 598 | 599 | /* 600 | build a Map that is className => { statics: memberName => Array, instances: memberName => Array } 601 | */ 602 | 603 | var classEntryMap = new Map>, instances:Map> }>(); 604 | for (entry in api.node.entries.nodes.entry) { 605 | var info = infoFromName(entry.att.name); 606 | var name = info.field; 607 | 608 | switch (entry.att.type) { 609 | case "method", "property": 610 | //ok 611 | case "selector": 612 | continue; 613 | default: 614 | throw "unknown entry type: " + entry.att.type; 615 | continue; 616 | } 617 | 618 | var entryMaps = classEntryMap.get(info.owner); 619 | if (entryMaps == null) { 620 | entryMaps = { statics: new Map(), instances: new Map() } 621 | classEntryMap.set(info.owner, entryMaps); 622 | } 623 | 624 | var entryMap = info.isStatic ? entryMaps.statics : entryMaps.instances; 625 | 626 | if (entryMap.exists(name)) 627 | entryMap.get(name).push(entry); 628 | else 629 | entryMap.set(name, [entry]); 630 | } 631 | 632 | /* 633 | put JQuery static fields into JQueryStatic 634 | */ 635 | 636 | var jQuery = classEntryMap.get("jQuery"); 637 | var jQueryStatic = if (noSeperatedStatic) { 638 | jQuery; 639 | } else { 640 | classEntryMap["jQueryStatic"] = { 641 | statics: jQuery.statics, 642 | instances: new Map() 643 | }; 644 | jQuery.statics = new Map(); 645 | classEntryMap["jQueryStatic"]; 646 | } 647 | 648 | /* 649 | start creating each class 650 | */ 651 | 652 | for (clsName in classEntryMap.keys()) { 653 | var entryMaps = classEntryMap.get(clsName); 654 | var type = { 655 | var types = toComplexType(clsName); 656 | types.length == 1 ? types[0] : throw clsName; //ensure it is mapped to a single haxe class 657 | } 658 | 659 | var fields:Array = []; 660 | 661 | // copy constructor function to its own class as "new" 662 | if (!entryMaps.instances.exists("new")) { 663 | var ctrName = clsName.charAt(0).toUpperCase() + clsName.substring(1); 664 | if (jQueryStatic.statics.exists(ctrName)) { 665 | entryMaps.instances.set("new", jQueryStatic.statics.get(ctrName)); 666 | } 667 | } 668 | 669 | for (isStatic in [true, false]) { 670 | var entryMap = isStatic ? entryMaps.statics : entryMaps.instances; 671 | var memNames = [for (n in entryMap.keys()) n]; 672 | memNames.sort(Reflect.compare); 673 | for (memName in memNames) { 674 | var mem = entryMap.get(memName); 675 | 676 | var field:Field = { 677 | name: memName, 678 | doc: "", 679 | access: isStatic ? [AStatic, APublic] : [APublic], 680 | kind: null, 681 | pos: null, 682 | meta: [] 683 | }; 684 | 685 | //in case there is a name collision in static field and instance field 686 | if (!noRenameStaticField && isStatic && entryMaps.instances.exists(field.name)) { 687 | var nativeName = field.name; 688 | field.name = nativeName + "Static"; 689 | field.meta.push({ 690 | name: ":native", 691 | params: [{expr: EConst(CString(nativeName)), pos:null}], 692 | pos: null 693 | }); 694 | } 695 | 696 | switch(memName) { 697 | case "catch": 698 | field.name = "_catch"; 699 | field.meta.push({ 700 | name:":native", 701 | params:[{ expr:EConst(CString("catch")), pos: null }], 702 | pos: null 703 | }); 704 | default: //pass 705 | } 706 | 707 | switch (memName) { 708 | case "fn": 709 | field.kind = FVar(macro:Dynamic, null); 710 | field.doc = "An alias to `jQuery.prototype`."; 711 | fields.push(field); 712 | case "fx": 713 | var _fields = []; 714 | for (entry in mem) { 715 | var types = toComplexType(entry.att.resolve("return"), entry); 716 | var field = Reflect.copy(field); 717 | field.name = entry.att.name.split(".")[2]; 718 | field.kind = FVar(either(types), null); 719 | field.access = []; 720 | field.meta = []; 721 | field.doc = entry.node.desc.innerHTML.trim(); 722 | 723 | var sig = entry.node.signature; 724 | var added = sig.hasNode.added ? sig.node.added.innerHTML : entry.has.added ? entry.att.added : null; 725 | var deprecated = sig.hasNode.deprecated ? sig.node.deprecated.innerHTML : entry.has.deprecated ? entry.att.deprecated : null; 726 | var removed = sig.hasNode.removed ? sig.node.removed.innerHTML : entry.has.removed ? entry.att.removed : null; 727 | 728 | if (noBuild) { 729 | if (deprecated != null) { 730 | field.meta.push({ 731 | name:":deprecated", 732 | params:[{ expr:EConst(CString('Deprecated since jQuery $deprecated')), pos: null }], 733 | pos: null 734 | }); 735 | } 736 | _fields.push(field); 737 | } else { 738 | var jQueryVersionFields = []; 739 | if (added != null) { 740 | jQueryVersionFields.push({ 741 | field: "added", 742 | expr : { expr: EConst(CString(added)), pos:null } 743 | }); 744 | } 745 | if (deprecated != null) { 746 | jQueryVersionFields.push({ 747 | field: "deprecated", 748 | expr : { expr: EConst(CString(deprecated)), pos:null } 749 | }); 750 | } 751 | if (removed != null) { 752 | jQueryVersionFields.push({ 753 | field: "removed", 754 | expr : { expr: EConst(CString(removed)), pos:null } 755 | }); 756 | } 757 | 758 | if (jQueryVersionFields.length > 0) { 759 | field.meta.push({ 760 | name:":jQueryVersion", 761 | params:[{ expr:EObjectDecl(jQueryVersionFields), pos: null }], 762 | pos: null 763 | }); 764 | } 765 | 766 | _fields.push(field); 767 | } 768 | } 769 | field.kind = FVar(TAnonymous(_fields), null); 770 | fields.push(field); 771 | 772 | default: 773 | var type = mem[0].att.type; 774 | switch (type) { 775 | case "method": 776 | //ensure all are methods 777 | if (!mem.foreach(function(m) return m.att.type == "method")){ 778 | throw memName + "is of types: " + [for (m in mem) m.att.type].join(", "); 779 | } 780 | 781 | var functions:Array<{ 782 | func: Function, 783 | config: FuncConfig 784 | }> = []; 785 | 786 | for (entry in mem) { 787 | for (sig in entry.nodes.signature) { 788 | var args:Array = [for (arg in sig.nodes.argument) 789 | { 790 | name: { 791 | var id = ~/(?:_*[a-z][_a-zA-Z0-9]*|_+[0-9][_a-zA-Z0-9]*|_*[A-Z][_a-zA-Z0-9]*|_+|\$[_a-zA-Z0-9]+)/; 792 | id.match(arg.att.name); 793 | var name = id.matched(0); 794 | if (keywords.indexOf(name) != -1) 795 | "_" + name; 796 | else 797 | name; 798 | }, 799 | opt: arg.has.optional && switch (arg.att.optional) { 800 | case "true": true; 801 | case "false": false; 802 | case unknown: throw unknown; 803 | }, 804 | type: either( 805 | arg.has.type ? 806 | toComplexType(arg.att.type, arg) 807 | : 808 | arg.hasNode.type ? 809 | arg.nodes.type.fold(function(t, a:Array) return a.concat(toComplexType(t.att.name, arg)), []) 810 | : 811 | toComplexType(null, arg) 812 | ) 813 | } 814 | ]; 815 | 816 | functions.push({ func:{ 817 | args: args, 818 | ret: switch(memName) { 819 | case "new": 820 | macro:Void; 821 | default: 822 | var types = if (entry.has.resolve("return")) { 823 | toComplexType(entry.att.resolve("return"), entry); 824 | } else { 825 | [for (r in entry.nodes.resolve("return")) r.att.type] 826 | .fold( 827 | function(t:String, ts:Array) return ts.concat(toComplexType(t, entry)), 828 | [] 829 | ); 830 | }; 831 | 832 | var et = either(types); 833 | Lambda.count(eitherTypes(et)) > 1 ? macro:Dynamic: et; 834 | }, 835 | expr: null, 836 | params: [] 837 | }, config:{ 838 | added: sig.hasNode.added ? sig.node.added.innerHTML : entry.has.added ? entry.att.added : null, 839 | deprecated: sig.hasNode.deprecated ? sig.node.deprecated.innerHTML : entry.has.deprecated ? entry.att.deprecated : null, 840 | removed: sig.hasNode.removed ? sig.node.removed.innerHTML : entry.has.removed ? entry.att.removed : null, 841 | doc: entry.hasNode.desc ? entry.node.desc.innerHTML.trim() : "" 842 | }}); 843 | } 844 | } 845 | 846 | //sort 847 | functions.sort(function(f0,f1) return compareFunctions(f0.func, f1.func)); 848 | 849 | if (memName == "new") { 850 | field.meta.push({ 851 | name:":selfCall", 852 | params:[], 853 | pos: null 854 | }); 855 | } 856 | 857 | if (memName == "readyException") { 858 | field.access.push(ADynamic); 859 | } 860 | 861 | if (noBuild) { 862 | if (functions.length == 0) 863 | continue; 864 | 865 | var deprecateds = [ 866 | for (f in functions) 867 | if (f.config.deprecated != null) 868 | f.config.deprecated 869 | ]; 870 | if (deprecateds.length > 0) { 871 | if (functions.length == 1) { 872 | var deprecated = deprecateds[0]; 873 | field.meta.push({ 874 | name:":deprecated", 875 | params:[{ expr:EConst(CString('Deprecated since jQuery $deprecated')), pos: null }], 876 | pos: null 877 | }); 878 | } else if (functions.length == deprecateds.length) { 879 | if (deprecateds.foreach(function(d) return d == deprecateds[0])) { 880 | var deprecated = deprecateds[0]; 881 | field.meta.push({ 882 | name:":deprecated", 883 | params:[{ expr:EConst(CString('Deprecated since jQuery $deprecated')), pos: null }], 884 | pos: null 885 | }); 886 | } else { 887 | field.meta.push({ 888 | name:":deprecated", 889 | params:[], 890 | pos: null 891 | }); 892 | } 893 | } 894 | } 895 | 896 | var doc = [ 897 | for (f in functions) 898 | if (f.config.doc != "") 899 | f.config.doc => f.config.doc 900 | ]; 901 | 902 | var func = functions.shift(); 903 | field.kind = FFun(func.func); 904 | 905 | for (func in functions) { 906 | func.func.expr = macro {}; 907 | field.meta.push({ 908 | name: ":overload", 909 | params: [{ expr: EFunction(null, func.func), pos: null }], 910 | pos: null 911 | }); 912 | } 913 | field.doc = [for (d in doc) d].join("\nOR\n"); 914 | 915 | fields.push(field); 916 | } else { 917 | //create Field for individual signature 918 | //the Config build macro will put them back to @:overload metas 919 | 920 | if (functions.length > 1) { 921 | field.meta.push({ 922 | name:":overload", 923 | params:[], 924 | pos: null 925 | }); 926 | } 927 | 928 | for (f in functions) { 929 | var clonedField = field.copy(); 930 | clonedField.kind = FFun(f.func); 931 | clonedField.doc = f.config.doc; 932 | clonedField.meta = field.meta.copy(); 933 | 934 | var jQueryVersionFields = []; 935 | if (f.config.added != null) { 936 | jQueryVersionFields.push({ 937 | field: "added", 938 | expr : { expr: EConst(CString(f.config.added)), pos:null } 939 | }); 940 | } 941 | if (f.config.deprecated != null) { 942 | jQueryVersionFields.push({ 943 | field: "deprecated", 944 | expr : { expr: EConst(CString(f.config.deprecated)), pos:null } 945 | }); 946 | } 947 | if (f.config.removed != null) { 948 | jQueryVersionFields.push({ 949 | field: "removed", 950 | expr : { expr: EConst(CString(f.config.removed)), pos:null } 951 | }); 952 | } 953 | if (jQueryVersionFields.length > 0) { 954 | clonedField.meta.push({ 955 | name:":jQueryVersion", 956 | params:[{ expr:EObjectDecl(jQueryVersionFields), pos: null }], 957 | pos: null 958 | }); 959 | } 960 | fields.push(clonedField); 961 | } 962 | } 963 | case "property": 964 | if (mem.length == 1 || memName == "browser") { 965 | var entry = if (mem.length == 1) { 966 | mem[0]; 967 | } else if (memName == "browser") { 968 | mem.find(function(e) return e.att.name.endsWith(".browser")); 969 | } else { 970 | throw mem; 971 | } 972 | var types = toComplexType(entry.att.resolve("return"), entry); 973 | field.kind = switch (memName) { 974 | case "length": FProp("default", "null", either(types), null); 975 | case _: FVar(either(types), null); 976 | } 977 | field.doc = entry.node.desc.innerHTML.trim(); 978 | 979 | var sig = entry.node.signature; 980 | var added = sig.hasNode.added ? sig.node.added.innerHTML : entry.has.added ? entry.att.added : null; 981 | var deprecated = sig.hasNode.deprecated ? sig.node.deprecated.innerHTML : entry.has.deprecated ? entry.att.deprecated : null; 982 | var removed = sig.hasNode.removed ? sig.node.removed.innerHTML : entry.has.removed ? entry.att.removed : null; 983 | 984 | if (noBuild) { 985 | if (deprecated != null) { 986 | field.meta.push({ 987 | name:":deprecated", 988 | params:[{ expr:EConst(CString('Deprecated since jQuery $deprecated')), pos: null }], 989 | pos: null 990 | }); 991 | } 992 | fields.push(field); 993 | } else { 994 | var jQueryVersionFields = []; 995 | if (added != null) { 996 | jQueryVersionFields.push({ 997 | field: "added", 998 | expr : { expr: EConst(CString(added)), pos:null } 999 | }); 1000 | } 1001 | if (deprecated != null) { 1002 | jQueryVersionFields.push({ 1003 | field: "deprecated", 1004 | expr : { expr: EConst(CString(deprecated)), pos:null } 1005 | }); 1006 | } 1007 | if (removed != null) { 1008 | jQueryVersionFields.push({ 1009 | field: "removed", 1010 | expr : { expr: EConst(CString(removed)), pos:null } 1011 | }); 1012 | } 1013 | if (jQueryVersionFields.length > 0) { 1014 | field.meta.push({ 1015 | name:":jQueryVersion", 1016 | params:[{ expr:EObjectDecl(jQueryVersionFields), pos: null }], 1017 | pos: null 1018 | }); 1019 | } 1020 | fields.push(field); 1021 | } 1022 | } else { 1023 | throw mem; 1024 | } 1025 | 1026 | default: 1027 | throw "unknown entry type: " + type; 1028 | } 1029 | } 1030 | } 1031 | } 1032 | 1033 | switch (type) { 1034 | case TPath(tp): 1035 | var td:TypeDefinition = { 1036 | pack : tp.pack, 1037 | name : tp.name, 1038 | pos : null, 1039 | meta : [], 1040 | params : [], 1041 | isExtern : true, 1042 | kind : TDClass(), 1043 | fields : fields 1044 | }; 1045 | 1046 | switch(tp.name) { 1047 | case "JQuery": 1048 | td.kind = TDClass(null, [{ 1049 | pack: [], 1050 | name: "ArrayAccess", 1051 | params: [TPType(element)] 1052 | }]); 1053 | 1054 | if (!noSeperatedStatic) 1055 | fields.push({ 1056 | name: "_static", 1057 | doc: "Compile-time short cut to JQueryStatic.", 1058 | access: [AInline, AStatic, APublic], 1059 | kind: FVar(null, macro $p{pack.split(".").concat(["JQueryStatic"])}), 1060 | pos: null, 1061 | meta: [] 1062 | }); 1063 | 1064 | if (addHaxeIterator) { 1065 | { 1066 | var JqIterator = jqType("JqIterator"); 1067 | var JqIteratorTPath = switch (JqIterator) { 1068 | case TPath(tp): tp; 1069 | case _: throw JqIterator; 1070 | } 1071 | var iteratorMethodBody = macro return new $JqIteratorTPath(this); 1072 | fields.push({ 1073 | name: "iterator", 1074 | doc: "Haxe iterator.", 1075 | access: [AInline, APublic], 1076 | kind: FFun({ 1077 | params: null, 1078 | args: [], 1079 | ret: JqIterator, 1080 | expr: iteratorMethodBody, 1081 | }), 1082 | meta: [{ 1083 | name: ":runtime", 1084 | pos: null 1085 | }], 1086 | pos: null 1087 | }); 1088 | } 1089 | { 1090 | var JqIterator = jqType("JqEltsIterator"); 1091 | var JqIteratorTPath = switch (JqIterator) { 1092 | case TPath(tp): tp; 1093 | case _: throw JqIterator; 1094 | } 1095 | var iteratorMethodBody = macro return new $JqIteratorTPath(this); 1096 | fields.push({ 1097 | name: "elements", 1098 | doc: "Haxe iterator.", 1099 | access: [AInline, APublic], 1100 | kind: FFun({ 1101 | params: null, 1102 | args: [], 1103 | ret: JqIterator, 1104 | expr: iteratorMethodBody, 1105 | }), 1106 | meta: [{ 1107 | name: ":runtime", 1108 | pos: null 1109 | }], 1110 | pos: null 1111 | }); 1112 | } 1113 | } 1114 | case "Event": 1115 | td.kind = TDClass({ 1116 | pack: ["js", "html"], 1117 | name: "Event", 1118 | params: [] 1119 | }); 1120 | 1121 | for (field in copiedEventFields) { 1122 | if (td.fields.exists(function(f) return f.name == field)) 1123 | continue; 1124 | 1125 | switch (field) { 1126 | case "char": 1127 | td.fields.push({ 1128 | access: [APublic], 1129 | kind: FVar(macro:Int), 1130 | name: field, 1131 | pos: null 1132 | }); 1133 | case "data": 1134 | td.fields.push({ 1135 | access: [APublic], 1136 | kind: FVar(macro:Dynamic), 1137 | name: field, 1138 | pos: null 1139 | }); 1140 | case "offsetX", "offsetY": 1141 | td.fields.push({ 1142 | access: [APublic], 1143 | kind: FVar(macro:Int), 1144 | name: field, 1145 | pos: null 1146 | }); 1147 | case "toElement": 1148 | td.fields.push({ 1149 | access: [APublic], 1150 | kind: FVar(macro:js.html.Element), 1151 | name: field, 1152 | pos: null 1153 | }); 1154 | case _: 1155 | var fInfo = coreEventFields.find(function(f) return f.name == field); 1156 | if (fInfo == null) { 1157 | trace(field); 1158 | continue; 1159 | } 1160 | td.fields.push({ 1161 | doc: fInfo.doc, 1162 | access: [APublic], 1163 | kind: switch (fInfo.kind) { 1164 | case FVar(read, write): FVar(fInfo.type); 1165 | case FMethod(k): throw "should be FVar"; 1166 | }, 1167 | name: field, 1168 | pos: null 1169 | }); 1170 | } 1171 | } 1172 | var evtFields:Array = getFields("js.html.Event"); 1173 | td.fields = td.fields.filter(function(field) return !evtFields.exists(function(f) return f.name == field.name)); 1174 | 1175 | // add getThis() helper method 1176 | // See the comment section of https://github.com/HaxeFoundation/haxe/commit/e3a022dd4bae85f8456cf3f1683fefd2e0b5d22d 1177 | { 1178 | var jq = jqType("JQuery"); 1179 | var JqTPath = switch (jq) { 1180 | case TPath(tp): tp; 1181 | case v: throw v; 1182 | } 1183 | td.fields.push({ 1184 | name: "getThis", 1185 | doc: "A convenient method of getting `$(this)`, which is typically the same as `$(evt.currentTarget)`.\n" 1186 | + "For detail, refer to https://api.jquery.com/event.currenttarget/.", 1187 | access: [AInline, APublic], 1188 | kind: FFun({ 1189 | params: null, 1190 | args: [], 1191 | ret: jq, 1192 | expr: macro return new $JqTPath(js.Lib.nativeThis), 1193 | }), 1194 | meta: [], 1195 | pos: null 1196 | }); 1197 | } 1198 | default: 1199 | //pass 1200 | } 1201 | 1202 | out.push(td); 1203 | default: //TODO 1204 | trace(type); 1205 | } 1206 | 1207 | } 1208 | 1209 | 1210 | var deferred = out.find(function(t) return t.name == "Deferred"); 1211 | var promiseFields = [ 1212 | for (field in deferred.fields) 1213 | // https://api.jquery.com/Types/#Promise 1214 | if ([ 1215 | "then", 1216 | "done", 1217 | "fail", 1218 | "always", 1219 | "pipe", 1220 | "progress", 1221 | "state", 1222 | "isResolved", 1223 | "isRejected" 1224 | ].indexOf(field.name) >= 0) 1225 | field 1226 | ]; 1227 | { 1228 | var td:TypeDefinition = { 1229 | pack : this.pack.split("."), 1230 | name : "JqXHR", 1231 | pos : null, 1232 | meta : [], 1233 | params : [], 1234 | isExtern : true, 1235 | kind : TDClass({ 1236 | pack: ["js", "html"], 1237 | name: "XMLHttpRequest", 1238 | params: [] 1239 | }), 1240 | fields : promiseFields 1241 | }; 1242 | out.push(td); 1243 | } 1244 | { 1245 | var td:TypeDefinition = { 1246 | pack : this.pack.split("."), 1247 | name : "Promise", 1248 | pos : null, 1249 | meta : [], 1250 | params : [], 1251 | isExtern : !noBuild, 1252 | kind : if (noBuild) { 1253 | TDStructure; 1254 | } else { 1255 | TDClass(); 1256 | }, 1257 | fields : promiseFields 1258 | }; 1259 | out.push(td); 1260 | } 1261 | 1262 | for (td in out) { 1263 | if (!noBuild) { 1264 | td.meta.push({ 1265 | name: ":build", 1266 | params: [macro $p{pack.split(".").concat(["Config", "build"])}()], 1267 | pos: null 1268 | }); 1269 | } 1270 | 1271 | if (noBuild) { 1272 | var native = switch (td.name) { 1273 | case "JQuery" | "JQueryStatic": 1274 | native; 1275 | case name: 1276 | native + "." + name; 1277 | } 1278 | td.meta.push({ 1279 | name: ":native", 1280 | params: [{ expr:EConst(CString(native)), pos: null }], 1281 | pos: null 1282 | }); 1283 | } 1284 | } 1285 | 1286 | return out; 1287 | } 1288 | 1289 | macro static function getFields(type:String) { 1290 | switch (haxe.macro.Context.getType(type)) { 1291 | case TInst(t, _): 1292 | var fields = [ 1293 | for (f in t.get().fields.get()) 1294 | { 1295 | type: switch (Context.toComplexType(f.type)) { 1296 | case TPath(tp) if (tp.name == "StdTypes"): 1297 | TPath({ 1298 | pack: tp.pack, 1299 | name: tp.sub 1300 | }); 1301 | case ct: ct; 1302 | }, 1303 | name: f.name, 1304 | kind: f.kind, 1305 | doc: f.doc 1306 | } 1307 | ]; 1308 | return macro $v{fields}; 1309 | case _: 1310 | throw type; 1311 | } 1312 | } 1313 | 1314 | #if (mcli && !macro) 1315 | public function runDefault():Void { 1316 | Sys.println('Generating jQuery core extern from "${apiXml}".'); 1317 | api = new Fast(Xml.parse(File.getContent(apiXml))).node.api; 1318 | 1319 | if (!FileSystem.exists(outputFolder)) 1320 | FileSystem.createDirectory(outputFolder); 1321 | Sys.setCwd(outputFolder); 1322 | 1323 | var tds = generate(); 1324 | 1325 | var printer = new Printer(); 1326 | for (td in tds) { 1327 | var clsStr = "/* This file is generated, do not edit! Visit https://api.jquery.com/ for API documentation. */\n" + printer.printTypeDefinition(td); 1328 | var packDir = td.pack.join("/"); 1329 | FileSystem.createDirectory(packDir); 1330 | File.saveContent(packDir + "/" + td.name + ".hx", clsStr); 1331 | } 1332 | Sys.println("Done."); 1333 | } 1334 | 1335 | /** 1336 | Print help message. 1337 | */ 1338 | public function help():Void { 1339 | Sys.println(showUsage()); 1340 | Sys.exit(0); 1341 | } 1342 | 1343 | static function main():Void { 1344 | new Dispatch(Sys.args()).dispatch(new ExternGenerator()); 1345 | } 1346 | #end 1347 | } -------------------------------------------------------------------------------- /js/jquery/Helper.hx: -------------------------------------------------------------------------------- 1 | package js.jquery; 2 | 3 | @:noPackageRestrict 4 | #if js extern #end class Helper { 5 | macro public static function J(exprs:Array) { 6 | return macro new js.jquery.JQuery($a{exprs}); 7 | } 8 | 9 | #if !macro 10 | public static var JTHIS(get, null) : js.jquery.JQuery; 11 | 12 | static inline function get_JTHIS() : js.jquery.JQuery { 13 | return new js.jquery.JQuery(js.Lib.nativeThis); 14 | } 15 | #end 16 | } -------------------------------------------------------------------------------- /js/jquery/JqEltsIterator.hx: -------------------------------------------------------------------------------- 1 | package js.jquery; 2 | 3 | class JqEltsIterator { 4 | var j:JQuery; 5 | var i:Int; 6 | inline public function new(j:JQuery):Void { 7 | this.i = 0; 8 | this.j = j; 9 | } 10 | inline public function hasNext():Bool { 11 | return i < j.length; 12 | } 13 | inline public function next():JQuery { 14 | return new JQuery(this.j[i++]); 15 | } 16 | 17 | static function __init__() { 18 | var typeofJQuery = #if (haxe_ver < 4) untyped __typeof__(JQuery) #else js.Syntax.typeof(JQuery) #end ; 19 | if (typeofJQuery != 'undefined' && JQuery.fn != null) 20 | JQuery.fn.elements = function() return new JqEltsIterator(js.Lib.nativeThis); 21 | } 22 | } -------------------------------------------------------------------------------- /js/jquery/JqIterator.hx: -------------------------------------------------------------------------------- 1 | package js.jquery; 2 | 3 | class JqIterator { 4 | var j:JQuery; 5 | var i:Int; 6 | inline public function new(j:JQuery):Void { 7 | this.i = 0; 8 | this.j = j; 9 | } 10 | inline public function hasNext():Bool { 11 | return i < j.length; 12 | } 13 | inline public function next():js.html.Element { 14 | return this.j[i++]; 15 | } 16 | 17 | static function __init__() { 18 | var typeofJQuery = #if (haxe_ver < 4) untyped __typeof__(JQuery) #else js.Syntax.typeof(JQuery) #end ; 19 | if (typeofJQuery != 'undefined' && JQuery.fn != null) 20 | JQuery.fn.iterator = function() return new JqIterator(js.Lib.nativeThis); 21 | } 22 | } -------------------------------------------------------------------------------- /js/jquery/JqXHR.hx: -------------------------------------------------------------------------------- 1 | /* This file is generated, do not edit! Visit https://api.jquery.com/ for API documentation. */ 2 | package js.jquery; 3 | @:build(js.jquery.Config.build()) extern class JqXHR extends js.html.XMLHttpRequest { 4 | /** 5 | Add handlers to be called when the Deferred object is either resolved or rejected. 6 | **/ 7 | @:jQueryVersion({ added : "1.6" }) 8 | public function always(alwaysCallbacks:haxe.extern.EitherType>, ?alwaysCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; 9 | /** 10 | Add handlers to be called when the Deferred object is resolved. 11 | **/ 12 | @:jQueryVersion({ added : "1.5" }) 13 | public function done(doneCallbacks:haxe.extern.EitherType>, ?doneCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; 14 | /** 15 | Add handlers to be called when the Deferred object is rejected. 16 | **/ 17 | @:jQueryVersion({ added : "1.5" }) 18 | public function fail(failCallbacks:haxe.extern.EitherType>, ?failCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; 19 | /** 20 | Determine whether a Deferred object has been rejected. 21 | **/ 22 | @:jQueryVersion({ added : "1.5", deprecated : "1.7", removed : "1.8" }) 23 | public function isRejected():Bool; 24 | /** 25 | Determine whether a Deferred object has been resolved. 26 | **/ 27 | @:jQueryVersion({ added : "1.5", deprecated : "1.7", removed : "1.8" }) 28 | public function isResolved():Bool; 29 | /** 30 | Utility method to filter and/or chain Deferreds. 31 | **/ 32 | @:overload 33 | @:jQueryVersion({ added : "1.6", deprecated : "1.8" }) 34 | public function pipe(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function):js.jquery.Promise; 35 | /** 36 | Utility method to filter and/or chain Deferreds. 37 | **/ 38 | @:overload 39 | @:jQueryVersion({ added : "1.7", deprecated : "1.8" }) 40 | public function pipe(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise; 41 | /** 42 | Add handlers to be called when the Deferred object generates progress notifications. 43 | **/ 44 | @:jQueryVersion({ added : "1.7" }) 45 | public function progress(progressCallbacks:haxe.extern.EitherType, Array>>, ?progressCallbacks:haxe.extern.EitherType, Array>>):js.jquery.Deferred; 46 | /** 47 | Determine the current state of a Deferred object. 48 | **/ 49 | @:jQueryVersion({ added : "1.7" }) 50 | public function state():String; 51 | /** 52 | Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. 53 | **/ 54 | @:overload 55 | @:jQueryVersion({ added : "1.5", removed : "1.8" }) 56 | public function then(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>):js.jquery.Promise; 57 | /** 58 | Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. 59 | **/ 60 | @:overload 61 | @:jQueryVersion({ added : "1.8" }) 62 | public function then(doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise; 63 | /** 64 | Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. 65 | **/ 66 | @:overload 67 | @:jQueryVersion({ added : "1.7", removed : "1.8" }) 68 | public function then(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>, ?progressCallbacks:haxe.extern.EitherType>):js.jquery.Promise; 69 | } -------------------------------------------------------------------------------- /js/jquery/Plugin.hx: -------------------------------------------------------------------------------- 1 | package js.jquery; 2 | 3 | import js.jquery.*; 4 | import haxe.macro.Expr; 5 | import haxe.macro.Context; 6 | 7 | /** 8 | Plugin is macro-based, responsible for copy-and-pasting the fields in the extern classes 9 | into JQuery and JQueryStatic. 10 | 11 | To write a jQuery plugin extern, create an extern class that implements Plugin, 12 | and start writing the members as if writing directly inside the JQuery class. 13 | 14 | To use an plugin extern, add the following compiler option: 15 | --macro js.jquery.Plugin.add('pack.JQueryPlugIn') 16 | **/ 17 | 18 | @:noPackageRestrict 19 | #if !macro @:autoBuild(js.jquery.PluginBuilder.build()) #end 20 | extern interface Plugin {} 21 | 22 | @:noPackageRestrict 23 | #if !macro extern #end 24 | class PluginBuilder { 25 | #if macro 26 | static public function build():Array { 27 | var plugin = Context.getLocalClass(); 28 | var pluginClass = plugin.get(); 29 | var pluginFullName = plugin.toString(); 30 | 31 | var compilerOption = "--macro js.jquery.Config.addPlugin('" + pluginFullName + "')"; 32 | 33 | if (Context.defined("debug") && !Config.plugins.exists(pluginFullName)) 34 | Context.warning('JQuery plugin being imported without compiler option: $compilerOption', pluginClass.pos); 35 | 36 | if (Config.isBuilt) 37 | Context.error('JQuery class is already built before inserting plugin. Most likely due to missing compiler option: $compilerOption', pluginClass.pos); 38 | 39 | if (!pluginClass.isExtern) 40 | Context.error("Plugin is for extern only.", pluginClass.pos); 41 | 42 | //mark the Plugin final 43 | pluginClass.meta.add(":final", [], pluginClass.pos); 44 | 45 | var fields = Context.getBuildFields(); 46 | Config.plugins.set(pluginFullName, fields); 47 | return []; 48 | } 49 | #end 50 | } -------------------------------------------------------------------------------- /js/jquery/Promise.hx: -------------------------------------------------------------------------------- 1 | /* This file is generated, do not edit! Visit https://api.jquery.com/ for API documentation. */ 2 | package js.jquery; 3 | @:build(js.jquery.Config.build()) extern class Promise { 4 | /** 5 | Add handlers to be called when the Deferred object is either resolved or rejected. 6 | **/ 7 | @:jQueryVersion({ added : "1.6" }) 8 | public function always(alwaysCallbacks:haxe.extern.EitherType>, ?alwaysCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; 9 | /** 10 | Add handlers to be called when the Deferred object is resolved. 11 | **/ 12 | @:jQueryVersion({ added : "1.5" }) 13 | public function done(doneCallbacks:haxe.extern.EitherType>, ?doneCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; 14 | /** 15 | Add handlers to be called when the Deferred object is rejected. 16 | **/ 17 | @:jQueryVersion({ added : "1.5" }) 18 | public function fail(failCallbacks:haxe.extern.EitherType>, ?failCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; 19 | /** 20 | Determine whether a Deferred object has been rejected. 21 | **/ 22 | @:jQueryVersion({ added : "1.5", deprecated : "1.7", removed : "1.8" }) 23 | public function isRejected():Bool; 24 | /** 25 | Determine whether a Deferred object has been resolved. 26 | **/ 27 | @:jQueryVersion({ added : "1.5", deprecated : "1.7", removed : "1.8" }) 28 | public function isResolved():Bool; 29 | /** 30 | Utility method to filter and/or chain Deferreds. 31 | **/ 32 | @:overload 33 | @:jQueryVersion({ added : "1.6", deprecated : "1.8" }) 34 | public function pipe(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function):js.jquery.Promise; 35 | /** 36 | Utility method to filter and/or chain Deferreds. 37 | **/ 38 | @:overload 39 | @:jQueryVersion({ added : "1.7", deprecated : "1.8" }) 40 | public function pipe(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise; 41 | /** 42 | Add handlers to be called when the Deferred object generates progress notifications. 43 | **/ 44 | @:jQueryVersion({ added : "1.7" }) 45 | public function progress(progressCallbacks:haxe.extern.EitherType, Array>>, ?progressCallbacks:haxe.extern.EitherType, Array>>):js.jquery.Deferred; 46 | /** 47 | Determine the current state of a Deferred object. 48 | **/ 49 | @:jQueryVersion({ added : "1.7" }) 50 | public function state():String; 51 | /** 52 | Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. 53 | **/ 54 | @:overload 55 | @:jQueryVersion({ added : "1.5", removed : "1.8" }) 56 | public function then(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>):js.jquery.Promise; 57 | /** 58 | Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. 59 | **/ 60 | @:overload 61 | @:jQueryVersion({ added : "1.8" }) 62 | public function then(doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise; 63 | /** 64 | Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. 65 | **/ 66 | @:overload 67 | @:jQueryVersion({ added : "1.7", removed : "1.8" }) 68 | public function then(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>, ?progressCallbacks:haxe.extern.EitherType>):js.jquery.Promise; 69 | } -------------------------------------------------------------------------------- /js/jquery/Thenable.hx: -------------------------------------------------------------------------------- 1 | package js.jquery; 2 | 3 | #if (haxe_ver >= 4) 4 | typedef Thenable = js.lib.Promise.Thenable; 5 | #else 6 | typedef Thenable = js.Promise.Thenable; 7 | #end -------------------------------------------------------------------------------- /js/jquery/Utils.hx: -------------------------------------------------------------------------------- 1 | package js.jquery; 2 | 3 | using Std; 4 | using StringTools; 5 | 6 | @:noPackageRestrict 7 | class Utils { 8 | static public function parseStringVersion(v:String):Array { 9 | return v.split(".").map(Std.parseInt); 10 | } 11 | 12 | static public function parseIntVersion(v:Int):Array { 13 | var major = (v/10000).int(); 14 | var minor = ((v - major * 10000) / 100).int(); 15 | var patch = v - major * 10000 - minor * 100; 16 | return [major, minor, patch]; 17 | } 18 | 19 | static public function versionToInt(v:Array):Int { 20 | return v[0] * 10000 + v[1] * 100 + v[2]; 21 | } 22 | 23 | static public function compareVersion(v0:Array, v1:Array):Int { 24 | var i:Int = 0, 25 | d:Int; 26 | 27 | while (i < v0.length && i < v1.length) { 28 | if ((d = v0[i] - v1[i]) != 0) 29 | return d; 30 | else 31 | ++i; 32 | } 33 | 34 | return 0; 35 | } 36 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-extern-for-haxe", 3 | "version": "3.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "abab": { 8 | "version": "2.0.5", 9 | "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", 10 | "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", 11 | "dev": true 12 | }, 13 | "acorn": { 14 | "version": "5.7.4", 15 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", 16 | "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", 17 | "dev": true 18 | }, 19 | "acorn-globals": { 20 | "version": "4.3.4", 21 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", 22 | "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", 23 | "dev": true, 24 | "requires": { 25 | "acorn": "^6.0.1", 26 | "acorn-walk": "^6.0.1" 27 | }, 28 | "dependencies": { 29 | "acorn": { 30 | "version": "6.4.2", 31 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", 32 | "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", 33 | "dev": true 34 | } 35 | } 36 | }, 37 | "acorn-walk": { 38 | "version": "6.2.0", 39 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", 40 | "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", 41 | "dev": true 42 | }, 43 | "ajv": { 44 | "version": "6.12.6", 45 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 46 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 47 | "dev": true, 48 | "requires": { 49 | "fast-deep-equal": "^3.1.1", 50 | "fast-json-stable-stringify": "^2.0.0", 51 | "json-schema-traverse": "^0.4.1", 52 | "uri-js": "^4.2.2" 53 | } 54 | }, 55 | "array-equal": { 56 | "version": "1.0.0", 57 | "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", 58 | "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", 59 | "dev": true 60 | }, 61 | "asn1": { 62 | "version": "0.2.4", 63 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 64 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 65 | "dev": true, 66 | "requires": { 67 | "safer-buffer": "~2.1.0" 68 | } 69 | }, 70 | "assert-plus": { 71 | "version": "1.0.0", 72 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 73 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 74 | "dev": true 75 | }, 76 | "async-limiter": { 77 | "version": "1.0.1", 78 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", 79 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", 80 | "dev": true 81 | }, 82 | "asynckit": { 83 | "version": "0.4.0", 84 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 85 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 86 | "dev": true 87 | }, 88 | "aws-sign2": { 89 | "version": "0.7.0", 90 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 91 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 92 | "dev": true 93 | }, 94 | "aws4": { 95 | "version": "1.11.0", 96 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", 97 | "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", 98 | "dev": true 99 | }, 100 | "bcrypt-pbkdf": { 101 | "version": "1.0.2", 102 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 103 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 104 | "dev": true, 105 | "requires": { 106 | "tweetnacl": "^0.14.3" 107 | } 108 | }, 109 | "browser-process-hrtime": { 110 | "version": "1.0.0", 111 | "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", 112 | "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", 113 | "dev": true 114 | }, 115 | "caseless": { 116 | "version": "0.12.0", 117 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 118 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 119 | "dev": true 120 | }, 121 | "combined-stream": { 122 | "version": "1.0.8", 123 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 124 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 125 | "dev": true, 126 | "requires": { 127 | "delayed-stream": "~1.0.0" 128 | } 129 | }, 130 | "core-util-is": { 131 | "version": "1.0.2", 132 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 133 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 134 | "dev": true 135 | }, 136 | "cssom": { 137 | "version": "0.3.8", 138 | "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", 139 | "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", 140 | "dev": true 141 | }, 142 | "cssstyle": { 143 | "version": "1.4.0", 144 | "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", 145 | "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", 146 | "dev": true, 147 | "requires": { 148 | "cssom": "0.3.x" 149 | } 150 | }, 151 | "dashdash": { 152 | "version": "1.14.1", 153 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 154 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 155 | "dev": true, 156 | "requires": { 157 | "assert-plus": "^1.0.0" 158 | } 159 | }, 160 | "data-urls": { 161 | "version": "1.1.0", 162 | "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", 163 | "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", 164 | "dev": true, 165 | "requires": { 166 | "abab": "^2.0.0", 167 | "whatwg-mimetype": "^2.2.0", 168 | "whatwg-url": "^7.0.0" 169 | }, 170 | "dependencies": { 171 | "whatwg-url": { 172 | "version": "7.1.0", 173 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", 174 | "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", 175 | "dev": true, 176 | "requires": { 177 | "lodash.sortby": "^4.7.0", 178 | "tr46": "^1.0.1", 179 | "webidl-conversions": "^4.0.2" 180 | } 181 | } 182 | } 183 | }, 184 | "deep-is": { 185 | "version": "0.1.4", 186 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 187 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 188 | "dev": true 189 | }, 190 | "delayed-stream": { 191 | "version": "1.0.0", 192 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 193 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 194 | "dev": true 195 | }, 196 | "domexception": { 197 | "version": "1.0.1", 198 | "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", 199 | "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", 200 | "dev": true, 201 | "requires": { 202 | "webidl-conversions": "^4.0.2" 203 | } 204 | }, 205 | "ecc-jsbn": { 206 | "version": "0.1.2", 207 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 208 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 209 | "dev": true, 210 | "requires": { 211 | "jsbn": "~0.1.0", 212 | "safer-buffer": "^2.1.0" 213 | } 214 | }, 215 | "escodegen": { 216 | "version": "1.14.3", 217 | "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", 218 | "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", 219 | "dev": true, 220 | "requires": { 221 | "esprima": "^4.0.1", 222 | "estraverse": "^4.2.0", 223 | "esutils": "^2.0.2", 224 | "optionator": "^0.8.1", 225 | "source-map": "~0.6.1" 226 | } 227 | }, 228 | "esprima": { 229 | "version": "4.0.1", 230 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 231 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 232 | "dev": true 233 | }, 234 | "estraverse": { 235 | "version": "4.3.0", 236 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 237 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 238 | "dev": true 239 | }, 240 | "esutils": { 241 | "version": "2.0.3", 242 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 243 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 244 | "dev": true 245 | }, 246 | "extend": { 247 | "version": "3.0.2", 248 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 249 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 250 | "dev": true 251 | }, 252 | "extsprintf": { 253 | "version": "1.3.0", 254 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 255 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 256 | "dev": true 257 | }, 258 | "fast-deep-equal": { 259 | "version": "3.1.3", 260 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 261 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 262 | "dev": true 263 | }, 264 | "fast-json-stable-stringify": { 265 | "version": "2.1.0", 266 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 267 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 268 | "dev": true 269 | }, 270 | "fast-levenshtein": { 271 | "version": "2.0.6", 272 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 273 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 274 | "dev": true 275 | }, 276 | "forever-agent": { 277 | "version": "0.6.1", 278 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 279 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 280 | "dev": true 281 | }, 282 | "form-data": { 283 | "version": "2.3.3", 284 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 285 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 286 | "dev": true, 287 | "requires": { 288 | "asynckit": "^0.4.0", 289 | "combined-stream": "^1.0.6", 290 | "mime-types": "^2.1.12" 291 | } 292 | }, 293 | "getpass": { 294 | "version": "0.1.7", 295 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 296 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 297 | "dev": true, 298 | "requires": { 299 | "assert-plus": "^1.0.0" 300 | } 301 | }, 302 | "har-schema": { 303 | "version": "2.0.0", 304 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 305 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 306 | "dev": true 307 | }, 308 | "har-validator": { 309 | "version": "5.1.5", 310 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 311 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 312 | "dev": true, 313 | "requires": { 314 | "ajv": "^6.12.3", 315 | "har-schema": "^2.0.0" 316 | } 317 | }, 318 | "html-encoding-sniffer": { 319 | "version": "1.0.2", 320 | "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", 321 | "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", 322 | "dev": true, 323 | "requires": { 324 | "whatwg-encoding": "^1.0.1" 325 | } 326 | }, 327 | "http-signature": { 328 | "version": "1.2.0", 329 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 330 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 331 | "dev": true, 332 | "requires": { 333 | "assert-plus": "^1.0.0", 334 | "jsprim": "^1.2.2", 335 | "sshpk": "^1.7.0" 336 | } 337 | }, 338 | "iconv-lite": { 339 | "version": "0.4.24", 340 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 341 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 342 | "dev": true, 343 | "requires": { 344 | "safer-buffer": ">= 2.1.2 < 3" 345 | } 346 | }, 347 | "is-typedarray": { 348 | "version": "1.0.0", 349 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 350 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 351 | "dev": true 352 | }, 353 | "isstream": { 354 | "version": "0.1.2", 355 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 356 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 357 | "dev": true 358 | }, 359 | "jquery": { 360 | "version": "3.6.0", 361 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", 362 | "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==", 363 | "dev": true 364 | }, 365 | "jsbn": { 366 | "version": "0.1.1", 367 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 368 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 369 | "dev": true 370 | }, 371 | "jsdom": { 372 | "version": "11.12.0", 373 | "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", 374 | "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", 375 | "dev": true, 376 | "requires": { 377 | "abab": "^2.0.0", 378 | "acorn": "^5.5.3", 379 | "acorn-globals": "^4.1.0", 380 | "array-equal": "^1.0.0", 381 | "cssom": ">= 0.3.2 < 0.4.0", 382 | "cssstyle": "^1.0.0", 383 | "data-urls": "^1.0.0", 384 | "domexception": "^1.0.1", 385 | "escodegen": "^1.9.1", 386 | "html-encoding-sniffer": "^1.0.2", 387 | "left-pad": "^1.3.0", 388 | "nwsapi": "^2.0.7", 389 | "parse5": "4.0.0", 390 | "pn": "^1.1.0", 391 | "request": "^2.87.0", 392 | "request-promise-native": "^1.0.5", 393 | "sax": "^1.2.4", 394 | "symbol-tree": "^3.2.2", 395 | "tough-cookie": "^2.3.4", 396 | "w3c-hr-time": "^1.0.1", 397 | "webidl-conversions": "^4.0.2", 398 | "whatwg-encoding": "^1.0.3", 399 | "whatwg-mimetype": "^2.1.0", 400 | "whatwg-url": "^6.4.1", 401 | "ws": "^5.2.0", 402 | "xml-name-validator": "^3.0.0" 403 | } 404 | }, 405 | "json-schema": { 406 | "version": "0.2.3", 407 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 408 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 409 | "dev": true 410 | }, 411 | "json-schema-traverse": { 412 | "version": "0.4.1", 413 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 414 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 415 | "dev": true 416 | }, 417 | "json-stringify-safe": { 418 | "version": "5.0.1", 419 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 420 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 421 | "dev": true 422 | }, 423 | "jsprim": { 424 | "version": "1.4.1", 425 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 426 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 427 | "dev": true, 428 | "requires": { 429 | "assert-plus": "1.0.0", 430 | "extsprintf": "1.3.0", 431 | "json-schema": "0.2.3", 432 | "verror": "1.10.0" 433 | } 434 | }, 435 | "left-pad": { 436 | "version": "1.3.0", 437 | "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", 438 | "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", 439 | "dev": true 440 | }, 441 | "levn": { 442 | "version": "0.3.0", 443 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 444 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 445 | "dev": true, 446 | "requires": { 447 | "prelude-ls": "~1.1.2", 448 | "type-check": "~0.3.2" 449 | } 450 | }, 451 | "lodash": { 452 | "version": "4.17.21", 453 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 454 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 455 | "dev": true 456 | }, 457 | "lodash.sortby": { 458 | "version": "4.7.0", 459 | "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", 460 | "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", 461 | "dev": true 462 | }, 463 | "mime-db": { 464 | "version": "1.49.0", 465 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", 466 | "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", 467 | "dev": true 468 | }, 469 | "mime-types": { 470 | "version": "2.1.32", 471 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", 472 | "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", 473 | "dev": true, 474 | "requires": { 475 | "mime-db": "1.49.0" 476 | } 477 | }, 478 | "nwsapi": { 479 | "version": "2.2.0", 480 | "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", 481 | "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", 482 | "dev": true 483 | }, 484 | "oauth-sign": { 485 | "version": "0.9.0", 486 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 487 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 488 | "dev": true 489 | }, 490 | "optionator": { 491 | "version": "0.8.3", 492 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", 493 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", 494 | "dev": true, 495 | "requires": { 496 | "deep-is": "~0.1.3", 497 | "fast-levenshtein": "~2.0.6", 498 | "levn": "~0.3.0", 499 | "prelude-ls": "~1.1.2", 500 | "type-check": "~0.3.2", 501 | "word-wrap": "~1.2.3" 502 | } 503 | }, 504 | "parse5": { 505 | "version": "4.0.0", 506 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", 507 | "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", 508 | "dev": true 509 | }, 510 | "performance-now": { 511 | "version": "2.1.0", 512 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 513 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", 514 | "dev": true 515 | }, 516 | "pn": { 517 | "version": "1.1.0", 518 | "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", 519 | "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", 520 | "dev": true 521 | }, 522 | "prelude-ls": { 523 | "version": "1.1.2", 524 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 525 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 526 | "dev": true 527 | }, 528 | "psl": { 529 | "version": "1.8.0", 530 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", 531 | "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", 532 | "dev": true 533 | }, 534 | "punycode": { 535 | "version": "2.1.1", 536 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 537 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 538 | "dev": true 539 | }, 540 | "qs": { 541 | "version": "6.5.2", 542 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 543 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", 544 | "dev": true 545 | }, 546 | "request": { 547 | "version": "2.88.2", 548 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 549 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 550 | "dev": true, 551 | "requires": { 552 | "aws-sign2": "~0.7.0", 553 | "aws4": "^1.8.0", 554 | "caseless": "~0.12.0", 555 | "combined-stream": "~1.0.6", 556 | "extend": "~3.0.2", 557 | "forever-agent": "~0.6.1", 558 | "form-data": "~2.3.2", 559 | "har-validator": "~5.1.3", 560 | "http-signature": "~1.2.0", 561 | "is-typedarray": "~1.0.0", 562 | "isstream": "~0.1.2", 563 | "json-stringify-safe": "~5.0.1", 564 | "mime-types": "~2.1.19", 565 | "oauth-sign": "~0.9.0", 566 | "performance-now": "^2.1.0", 567 | "qs": "~6.5.2", 568 | "safe-buffer": "^5.1.2", 569 | "tough-cookie": "~2.5.0", 570 | "tunnel-agent": "^0.6.0", 571 | "uuid": "^3.3.2" 572 | } 573 | }, 574 | "request-promise-core": { 575 | "version": "1.1.4", 576 | "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", 577 | "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", 578 | "dev": true, 579 | "requires": { 580 | "lodash": "^4.17.19" 581 | } 582 | }, 583 | "request-promise-native": { 584 | "version": "1.0.9", 585 | "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", 586 | "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", 587 | "dev": true, 588 | "requires": { 589 | "request-promise-core": "1.1.4", 590 | "stealthy-require": "^1.1.1", 591 | "tough-cookie": "^2.3.3" 592 | } 593 | }, 594 | "safe-buffer": { 595 | "version": "5.2.1", 596 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 597 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 598 | "dev": true 599 | }, 600 | "safer-buffer": { 601 | "version": "2.1.2", 602 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 603 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 604 | "dev": true 605 | }, 606 | "sax": { 607 | "version": "1.2.4", 608 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 609 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", 610 | "dev": true 611 | }, 612 | "source-map": { 613 | "version": "0.6.1", 614 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 615 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 616 | "dev": true, 617 | "optional": true 618 | }, 619 | "sshpk": { 620 | "version": "1.16.1", 621 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 622 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 623 | "dev": true, 624 | "requires": { 625 | "asn1": "~0.2.3", 626 | "assert-plus": "^1.0.0", 627 | "bcrypt-pbkdf": "^1.0.0", 628 | "dashdash": "^1.12.0", 629 | "ecc-jsbn": "~0.1.1", 630 | "getpass": "^0.1.1", 631 | "jsbn": "~0.1.0", 632 | "safer-buffer": "^2.0.2", 633 | "tweetnacl": "~0.14.0" 634 | } 635 | }, 636 | "stealthy-require": { 637 | "version": "1.1.1", 638 | "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", 639 | "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", 640 | "dev": true 641 | }, 642 | "symbol-tree": { 643 | "version": "3.2.4", 644 | "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", 645 | "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", 646 | "dev": true 647 | }, 648 | "tough-cookie": { 649 | "version": "2.5.0", 650 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 651 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 652 | "dev": true, 653 | "requires": { 654 | "psl": "^1.1.28", 655 | "punycode": "^2.1.1" 656 | } 657 | }, 658 | "tr46": { 659 | "version": "1.0.1", 660 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", 661 | "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", 662 | "dev": true, 663 | "requires": { 664 | "punycode": "^2.1.0" 665 | } 666 | }, 667 | "tunnel-agent": { 668 | "version": "0.6.0", 669 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 670 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 671 | "dev": true, 672 | "requires": { 673 | "safe-buffer": "^5.0.1" 674 | } 675 | }, 676 | "tweetnacl": { 677 | "version": "0.14.5", 678 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 679 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 680 | "dev": true 681 | }, 682 | "type-check": { 683 | "version": "0.3.2", 684 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 685 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 686 | "dev": true, 687 | "requires": { 688 | "prelude-ls": "~1.1.2" 689 | } 690 | }, 691 | "uri-js": { 692 | "version": "4.4.1", 693 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 694 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 695 | "dev": true, 696 | "requires": { 697 | "punycode": "^2.1.0" 698 | } 699 | }, 700 | "uuid": { 701 | "version": "3.4.0", 702 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 703 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 704 | "dev": true 705 | }, 706 | "verror": { 707 | "version": "1.10.0", 708 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 709 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 710 | "dev": true, 711 | "requires": { 712 | "assert-plus": "^1.0.0", 713 | "core-util-is": "1.0.2", 714 | "extsprintf": "^1.2.0" 715 | } 716 | }, 717 | "w3c-hr-time": { 718 | "version": "1.0.2", 719 | "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", 720 | "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", 721 | "dev": true, 722 | "requires": { 723 | "browser-process-hrtime": "^1.0.0" 724 | } 725 | }, 726 | "webidl-conversions": { 727 | "version": "4.0.2", 728 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", 729 | "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", 730 | "dev": true 731 | }, 732 | "whatwg-encoding": { 733 | "version": "1.0.5", 734 | "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", 735 | "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", 736 | "dev": true, 737 | "requires": { 738 | "iconv-lite": "0.4.24" 739 | } 740 | }, 741 | "whatwg-mimetype": { 742 | "version": "2.3.0", 743 | "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", 744 | "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", 745 | "dev": true 746 | }, 747 | "whatwg-url": { 748 | "version": "6.5.0", 749 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", 750 | "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", 751 | "dev": true, 752 | "requires": { 753 | "lodash.sortby": "^4.7.0", 754 | "tr46": "^1.0.1", 755 | "webidl-conversions": "^4.0.2" 756 | } 757 | }, 758 | "word-wrap": { 759 | "version": "1.2.3", 760 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 761 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 762 | "dev": true 763 | }, 764 | "ws": { 765 | "version": "5.2.3", 766 | "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", 767 | "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", 768 | "dev": true, 769 | "requires": { 770 | "async-limiter": "~1.0.0" 771 | } 772 | }, 773 | "xml-name-validator": { 774 | "version": "3.0.0", 775 | "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", 776 | "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", 777 | "dev": true 778 | } 779 | } 780 | } 781 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-extern-for-haxe", 3 | "version": "3.0.0", 4 | "description": "This version of jQuery extern requires Haxe 3.3+. Users of Haxe 3.2.0- should checkout [jQueryExtern 2.0.4](https://github.com/andyli/jQueryExternForHaxe/tree/2.0.4).", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "dependencies": {}, 10 | "devDependencies": { 11 | "jquery": "^3.2.1", 12 | "jsdom": "^11.3.0" 13 | }, 14 | "scripts": { 15 | "test": "echo \"Error: no test specified\" && exit 1" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/andyli/jQueryExternForHaxe.git" 20 | }, 21 | "keywords": [ 22 | "haxe" 23 | ], 24 | "author": "Andy Li", 25 | "license": "Unlicense", 26 | "bugs": { 27 | "url": "https://github.com/andyli/jQueryExternForHaxe/issues" 28 | }, 29 | "homepage": "https://github.com/andyli/jQueryExternForHaxe#readme" 30 | } 31 | -------------------------------------------------------------------------------- /test.hxml: -------------------------------------------------------------------------------- 1 | -js test/bin/Test.js 2 | -main Test 3 | -cp test 4 | -lib phantomjs 5 | -lib utest 6 | -lib jQueryExtern 7 | -D travis -------------------------------------------------------------------------------- /test/DummyPlugin.hx: -------------------------------------------------------------------------------- 1 | extern class DummyPlugin 2 | implements js.jquery.Plugin 3 | { 4 | inline public function dummyMethod():JQuery return this; 5 | public var dummyProperty(get,null):Int; 6 | inline public function get_dummyProperty():Int return 123; 7 | 8 | inline static public function staticDummyMethod():String return "static dummy"; 9 | inline static public var staticDummyProperty:Int = 456; 10 | } -------------------------------------------------------------------------------- /test/DummyPlugin2.hx: -------------------------------------------------------------------------------- 1 | extern class DummyPlugin2 2 | implements js.jquery.Plugin 3 | { 4 | inline public function dummyMethod2():String return "dummy"; 5 | } -------------------------------------------------------------------------------- /test/PhantomRunner.hx: -------------------------------------------------------------------------------- 1 | import js.phantomjs.*; 2 | 3 | class PhantomRunner { 4 | static public function main():Void { 5 | //log is 'prettier' than trace that does not includes source pos... 6 | var log = js.Browser.window.console.log; 7 | 8 | //setup a server to serve html 9 | var port = 8088; 10 | var server = WebServer.create(); 11 | server.listen(port, function(request:Request, response:Response):Void { 12 | var fullpath = Phantom.libraryPath + request.url; 13 | if (FileSystem.exists(fullpath)) { 14 | response.statusCode = 200; 15 | response.write(FileSystem.read(fullpath)); 16 | response.close(); 17 | } else { 18 | response.statusCode = 404; 19 | response.close(); 20 | } 21 | }); 22 | 23 | //open the test page which loads this script 24 | var page = WebPage.create(); 25 | 26 | //receive the test result 27 | page.onConsoleMessage = function(msg:String):Void { 28 | log(msg); 29 | var success = msg.indexOf("success: true") >= 0; 30 | Phantom.exit(success ? 0 : 1); 31 | } 32 | 33 | page.open('http://localhost:${port}/test.html', function(status) { 34 | if (status != "success") { 35 | Phantom.exit(1); 36 | } 37 | }); 38 | } 39 | } -------------------------------------------------------------------------------- /test/RunCi.hx: -------------------------------------------------------------------------------- 1 | import Sys.*; 2 | import sys.io.*; 3 | 4 | class RunCi { 5 | static function cmd(p:String, args:Array):Void { 6 | println('cmd: $p, args: $args'); 7 | var proc = new Process(p, args); 8 | 9 | var out = proc.stdout.readAll().toString(); 10 | if (out.length > 0) 11 | println(out); 12 | 13 | var err = proc.stderr.readAll().toString(); 14 | if (err.length > 0) 15 | println(err); 16 | 17 | var exitCode = proc.exitCode(); 18 | println('cmd exited with $exitCode'); 19 | if (exitCode != 0) { 20 | exit(1); 21 | } 22 | } 23 | static function main() { 24 | var args = [ 25 | "-js", "test/bin/Test.js", 26 | "-main", "Test", 27 | "-cp", "test", 28 | "-lib", "utest", 29 | "-lib", "jQueryExtern", 30 | "-D", "travis" 31 | ]; 32 | 33 | var pack = "js.jquery"; 34 | 35 | for (plugins in [ 36 | [], 37 | ["-D", "test_plugin", "--macro", "js.jquery.Config.addPlugin('DummyPlugin')", "--macro", "js.jquery.Config.addPlugin('DummyPlugin2')"] 38 | ]) 39 | for (setNative in [ 40 | [], 41 | ["--macro", pack + ".Config.setNative('jQuery')"] 42 | ]) 43 | for (setAllowDeprecated in [ 44 | [], 45 | ["--macro", pack + ".Config.setAllowDeprecated(true)"] 46 | ]) 47 | for (unflatten in [[], ["-D", "js-unflatten"]]) 48 | { 49 | var args = args 50 | .concat(plugins) 51 | .concat(setNative) 52 | .concat(setAllowDeprecated) 53 | .concat(unflatten); 54 | cmd("haxe", args); 55 | cmd("phantomjs", ["test/bin/PhantomRunner.js"]); 56 | 57 | cmd("haxe", args.concat(["-lib", "hxnodejs"])); 58 | cmd("node", ["test/bin/Test.js"]); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /test/Test.hx: -------------------------------------------------------------------------------- 1 | import utest.*; 2 | import js.*; 3 | import js.jquery.*; 4 | 5 | class Test { 6 | static function main():Void { 7 | #if hxnodejs 8 | var runner = new Runner(); 9 | runner.addCase(new TestNode()); 10 | var report = utest.ui.Report.create(runner); 11 | runner.run(); 12 | #else 13 | new JQuery(function(){ 14 | var runner = new Runner(); 15 | runner.addCase(new TestExtern()); 16 | #if test_plugin 17 | runner.addCase(new TestPlugin()); 18 | #end 19 | runner.addCase(new TestExternGenerator()); 20 | runner.addCase(new TestUtils()); 21 | var report = utest.ui.Report.create(runner); 22 | runner.run(); 23 | }); 24 | #end 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/TestExtern.hx: -------------------------------------------------------------------------------- 1 | import haxe.macro.Context; 2 | import js.jquery.*; 3 | import js.jquery.Helper.*; 4 | import utest.*; 5 | 6 | class TestExtern { 7 | public function new() {}; 8 | 9 | function testBasic() { 10 | var j = new JQuery("
"); 11 | Assert.equals(1, j.length); 12 | } 13 | 14 | function testRenamedStaticFields() { 15 | JQuery.each([123], function(i, e) { 16 | Assert.equals(0, i); 17 | Assert.equals(123, e); 18 | }); 19 | } 20 | 21 | function testIterator() { 22 | var div = Lambda.find(new JQuery("
"), function(ele) return ele.tagName.toLowerCase() == "div"); 23 | Assert.equals("div", div.tagName.toLowerCase()); 24 | } 25 | 26 | function testHelper() { 27 | var j = J("
"); 28 | j.each(function(i,e){ 29 | Assert.equals("test", JTHIS.attr("id")); 30 | }); 31 | } 32 | 33 | function testVersion() { 34 | var versionStr:String = JQuery.fn.jquery; 35 | var v = versionStr.split("."); 36 | Assert.equals(3, v.length); 37 | var versionFormatted = v[0] + StringTools.lpad(v[1], "0", 2) + StringTools.lpad(v[2], "0", 2); 38 | var versionAsInt = Std.parseInt(versionFormatted); 39 | var definedVersionAsInt = Std.parseInt(haxe.macro.Compiler.getDefine("jquery_ver")); 40 | 41 | Assert.isTrue(versionAsInt > 0); 42 | Assert.isTrue(definedVersionAsInt > 0); 43 | 44 | // For Haxe 3, in which std lib has its own jQuery extern, jquery_ver is already defined as its supported version. 45 | // For Haxe 4, in which the std jQuery extern is removed, jquery_ver is defined as jQueryExtern's supported version. 46 | // In general, we can just test whether the test runtime loaded jQuery is more updated than the extern version. 47 | Assert.isTrue(versionAsInt >= definedVersionAsInt); 48 | } 49 | } -------------------------------------------------------------------------------- /test/TestExternGenerator.hx: -------------------------------------------------------------------------------- 1 | import js.jquery.ExternGenerator; 2 | import utest.*; 3 | using Lambda; 4 | 5 | class TestExternGenerator { 6 | public function new() {}; 7 | 8 | public function testCompareComplexType():Void { 9 | Assert.isTrue(ExternGenerator.compareComplexType(macro:Dynamic, macro:Void) > 0); 10 | Assert.isTrue(ExternGenerator.compareComplexType(macro:Dynamic, macro:String) > 0); 11 | Assert.isTrue(ExternGenerator.compareComplexType(macro:Dynamic, macro:Int) > 0); 12 | Assert.isTrue(ExternGenerator.compareComplexType(macro:Dynamic, macro:Float) > 0); 13 | 14 | Assert.isTrue(ExternGenerator.compareComplexType(macro:Dynamic, macro:Void) > 0); 15 | Assert.isTrue(ExternGenerator.compareComplexType(macro:Dynamic, macro:String) > 0); 16 | Assert.isTrue(ExternGenerator.compareComplexType(macro:Dynamic, macro:Int) > 0); 17 | Assert.isTrue(ExternGenerator.compareComplexType(macro:Dynamic, macro:Float) > 0); 18 | 19 | Assert.isTrue(ExternGenerator.compareComplexType(macro:Dynamic, macro:Dynamic) > 0); 20 | 21 | Assert.isTrue(ExternGenerator.compareComplexType(macro:Float, macro:Int) > 0); 22 | } 23 | 24 | public function testCompareComplexTypeSorting():Void { 25 | var types = [ 26 | macro:Dynamic, //0 27 | macro:Dynamic, //1 28 | macro:String, //2 29 | macro:Float, //3 30 | macro:Int, //4 31 | macro:{a:Int}, //5 32 | macro:{a:Int, b:Int} //6 33 | ]; 34 | var sorted = types.copy(); 35 | 36 | sorted.sort(ExternGenerator.compareComplexType); 37 | 38 | Assert.equals( 39 | "2,4,3,6,5,1,0", 40 | sorted.map(function(_) return types.indexOf(_)).toString() 41 | ); 42 | 43 | sorted.sort(function(a,b) return -ExternGenerator.compareComplexType(a,b)); 44 | Assert.equals( 45 | "0,1,5,6,3,4,2", 46 | sorted.map(function(_) return types.indexOf(_)).toString() 47 | ); 48 | } 49 | 50 | public function testCompareFunctions():Void { 51 | var funcs = [ 52 | ExternGenerator.funcSig(function(a:Int, b:Int){}), 53 | ExternGenerator.funcSig(function(a:Int){}), 54 | ]; 55 | var sorted = funcs.copy(); 56 | sorted.sort(ExternGenerator.compareFunctions); 57 | Assert.equals(funcs[1], sorted[0]); 58 | 59 | var funcs = [ 60 | ExternGenerator.funcSig(function(a:Int, b:Int){}), 61 | ExternGenerator.funcSig(function(a:Int, b:Float){}), 62 | ]; 63 | var sorted = funcs.copy(); 64 | sorted.sort(ExternGenerator.compareFunctions); 65 | Assert.equals(funcs[0], sorted[0]); 66 | sorted.sort(function(a,b) return -ExternGenerator.compareFunctions(a,b)); 67 | Assert.equals(funcs[1], sorted[0]); 68 | } 69 | } -------------------------------------------------------------------------------- /test/TestNode.hx: -------------------------------------------------------------------------------- 1 | import js.jquery.*; 2 | import utest.*; 3 | 4 | #if (haxe_ver >= 4) 5 | import js.lib.Promise; 6 | #else 7 | import js.Promise; 8 | #end 9 | 10 | @:jsRequire("jsdom", "JSDOM") 11 | extern class JSDOM implements Dynamic { 12 | public function new(str:String, ?options:Dynamic):Void; 13 | 14 | static public function fromURL(url:String, ?options:Dynamic):Promise; 15 | static public function fromFile(url:String, ?options:Dynamic):Promise; 16 | } 17 | 18 | class TestNode { 19 | public function new():Void {} 20 | function test():Void { 21 | var dom = new JSDOM(""); 22 | var window = dom.window; 23 | var j = new JQuery(window); 24 | Assert.notNull(j); 25 | } 26 | } -------------------------------------------------------------------------------- /test/TestPlugin.hx: -------------------------------------------------------------------------------- 1 | import js.jquery.*; 2 | import utest.*; 3 | 4 | class TestPlugin { 5 | public function new() {}; 6 | 7 | public function testInstanceMember():Void { 8 | var j = new JQuery(); 9 | Assert.equals(j, j.dummyMethod()); 10 | Assert.equals(123, new JQuery().dummyProperty); 11 | } 12 | 13 | public function testStaticMember():Void { 14 | #if (haxe_ver >= 3.3) 15 | Assert.equals("static dummy", JQuery.staticDummyMethod()); 16 | Assert.equals(456, JQuery.staticDummyProperty); 17 | #else 18 | Assert.equals("static dummy", JQuery._static.staticDummyMethod()); 19 | Assert.equals(456, JQueryStatic.staticDummyProperty); 20 | #end 21 | } 22 | 23 | public function testInstanceMember2():Void { 24 | Assert.equals("dummy", new JQuery().dummyMethod2()); 25 | } 26 | } -------------------------------------------------------------------------------- /test/TestUtils.hx: -------------------------------------------------------------------------------- 1 | import js.jquery.Utils; 2 | import utest.*; 3 | using Std; 4 | 5 | class TestUtils { 6 | public function new() {}; 7 | 8 | function testCompareVersion():Void { 9 | var v = Utils.parseStringVersion("1.8.2"); 10 | Assert.equals(0, Utils.compareVersion(v, Utils.parseStringVersion("1.8.2"))); 11 | Assert.equals(1, Utils.compareVersion(v, Utils.parseStringVersion("1.8.1"))); 12 | Assert.equals(-1, Utils.compareVersion(v, Utils.parseStringVersion("1.8.3"))); 13 | } 14 | 15 | function test_parseIntVersion():Void { 16 | Assert.equals([1, 11, 3].string(), Utils.parseIntVersion(11103).string()); 17 | } 18 | 19 | function test_versionToInt():Void { 20 | Assert.equals(11103, Utils.versionToInt([1, 11, 3])); 21 | } 22 | } -------------------------------------------------------------------------------- /test/bin/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Test 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | The values stored were and 21 |
22 | 23 | 24 | --------------------------------------------------------------------------------