diff options
282 files changed, 2129 insertions, 6492 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f188ee29223..12385b293c0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.7-phantomjs-2.1-node-7.1" +image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.7-phantomjs-2.1-node-7.1-postgresql-9.6" cache: key: "ruby-233" @@ -10,8 +10,6 @@ variables: RAILS_ENV: "test" NODE_ENV: "test" SIMPLECOV: "true" - SETUP_DB: "true" - USE_BUNDLE_INSTALL: "true" GIT_DEPTH: "20" PHANTOMJS_VERSION: "2.1.1" GET_SOURCES_ATTEMPTS: "3" @@ -19,12 +17,9 @@ variables: KNAPSACK_SPINACH_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/spinach_report-master.json before_script: - - source ./scripts/prepare_build.sh - - cp config/gitlab.yml.example config/gitlab.yml - bundle --version - - '[ "$USE_BUNDLE_INSTALL" != "true" ] || retry bundle install --without postgres production --jobs $(nproc) --clean $FLAGS' - - retry gem install knapsack fog-aws mime-types - - '[ "$SETUP_DB" != "true" ] || bundle exec rake db:drop db:create db:schema:load db:migrate add_limits_mysql' + - . scripts/utils.sh + - ./scripts/prepare_build.sh stages: - prepare @@ -52,20 +47,34 @@ stages: paths: - knapsack/ -.use-db: &use-db +.use-pg: &use-pg + services: + - postgres:latest + - redis:alpine + +.use-mysql: &use-mysql services: - mysql:latest - redis:alpine +.only-master-and-ee-or-mysql: &only-master-and-ee-or-mysql + only: + - /\-(?i)mysql$/ + - master@gitlab-org/gitlab-ce + - master@gitlab/gitlabhq + - tags@gitlab-org/gitlab-ce + - tags@gitlab/gitlabhq + - //@gitlab-org/gitlab-ee + - //@gitlab/gitlab-ee + .rspec-knapsack: &rspec-knapsack stage: test <<: *dedicated-runner - <<: *use-db script: - JOB_NAME=( $CI_JOB_NAME ) - - export CI_NODE_INDEX=${JOB_NAME[1]} - - export CI_NODE_TOTAL=${JOB_NAME[2]} - - export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json + - export CI_NODE_INDEX=${JOB_NAME[-2]} + - export CI_NODE_TOTAL=${JOB_NAME[-1]} + - export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_${JOB_NAME[1]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json - export KNAPSACK_GENERATE_REPORT=true - export CACHE_CLASSES=true - cp ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH} @@ -78,15 +87,23 @@ stages: - knapsack/ - tmp/capybara/ +.rspec-knapsack-pg: &rspec-knapsack-pg + <<: *rspec-knapsack + <<: *use-pg + +.rspec-knapsack-mysql: &rspec-knapsack-mysql + <<: *rspec-knapsack + <<: *use-mysql + <<: *only-master-and-ee-or-mysql + .spinach-knapsack: &spinach-knapsack stage: test <<: *dedicated-runner - <<: *use-db script: - JOB_NAME=( $CI_JOB_NAME ) - - export CI_NODE_INDEX=${JOB_NAME[1]} - - export CI_NODE_TOTAL=${JOB_NAME[2]} - - export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json + - export CI_NODE_INDEX=${JOB_NAME[-2]} + - export CI_NODE_TOTAL=${JOB_NAME[-1]} + - export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_${JOB_NAME[1]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json - export KNAPSACK_GENERATE_REPORT=true - export CACHE_CLASSES=true - cp ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH} @@ -99,6 +116,15 @@ stages: - knapsack/ - tmp/capybara/ +.spinach-knapsack-pg: &spinach-knapsack-pg + <<: *spinach-knapsack + <<: *use-pg + +.spinach-knapsack-mysql: &spinach-knapsack-mysql + <<: *spinach-knapsack + <<: *use-mysql + <<: *only-master-and-ee-or-mysql + # Prepare and merge knapsack tests knapsack: <<: *knapsack-state @@ -116,8 +142,8 @@ update-knapsack: <<: *dedicated-runner stage: post-test script: - - scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_node_*.json - - scripts/merge-reports ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/spinach_node_*.json + - scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_pg_node_*.json + - scripts/merge-reports ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/spinach_pg_node_*.json - '[[ -z ${KNAPSACK_S3_BUCKET} ]] || scripts/sync-reports put $KNAPSACK_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH $KNAPSACK_SPINACH_SUITE_REPORT_PATH' - rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json only: @@ -127,7 +153,7 @@ update-knapsack: - master@gitlab/gitlab-ee setup-test-env: - <<: *use-db + <<: *use-pg <<: *dedicated-runner stage: prepare script: @@ -142,37 +168,69 @@ setup-test-env: - public/assets - tmp/tests -rspec 0 20: *rspec-knapsack -rspec 1 20: *rspec-knapsack -rspec 2 20: *rspec-knapsack -rspec 3 20: *rspec-knapsack -rspec 4 20: *rspec-knapsack -rspec 5 20: *rspec-knapsack -rspec 6 20: *rspec-knapsack -rspec 7 20: *rspec-knapsack -rspec 8 20: *rspec-knapsack -rspec 9 20: *rspec-knapsack -rspec 10 20: *rspec-knapsack -rspec 11 20: *rspec-knapsack -rspec 12 20: *rspec-knapsack -rspec 13 20: *rspec-knapsack -rspec 14 20: *rspec-knapsack -rspec 15 20: *rspec-knapsack -rspec 16 20: *rspec-knapsack -rspec 17 20: *rspec-knapsack -rspec 18 20: *rspec-knapsack -rspec 19 20: *rspec-knapsack - -spinach 0 10: *spinach-knapsack -spinach 1 10: *spinach-knapsack -spinach 2 10: *spinach-knapsack -spinach 3 10: *spinach-knapsack -spinach 4 10: *spinach-knapsack -spinach 5 10: *spinach-knapsack -spinach 6 10: *spinach-knapsack -spinach 7 10: *spinach-knapsack -spinach 8 10: *spinach-knapsack -spinach 9 10: *spinach-knapsack +rspec pg 0 20: *rspec-knapsack-pg +rspec pg 1 20: *rspec-knapsack-pg +rspec pg 2 20: *rspec-knapsack-pg +rspec pg 3 20: *rspec-knapsack-pg +rspec pg 4 20: *rspec-knapsack-pg +rspec pg 5 20: *rspec-knapsack-pg +rspec pg 6 20: *rspec-knapsack-pg +rspec pg 7 20: *rspec-knapsack-pg +rspec pg 8 20: *rspec-knapsack-pg +rspec pg 9 20: *rspec-knapsack-pg +rspec pg 10 20: *rspec-knapsack-pg +rspec pg 11 20: *rspec-knapsack-pg +rspec pg 12 20: *rspec-knapsack-pg +rspec pg 13 20: *rspec-knapsack-pg +rspec pg 14 20: *rspec-knapsack-pg +rspec pg 15 20: *rspec-knapsack-pg +rspec pg 16 20: *rspec-knapsack-pg +rspec pg 17 20: *rspec-knapsack-pg +rspec pg 18 20: *rspec-knapsack-pg +rspec pg 19 20: *rspec-knapsack-pg + +rspec mysql 0 20: *rspec-knapsack-mysql +rspec mysql 1 20: *rspec-knapsack-mysql +rspec mysql 2 20: *rspec-knapsack-mysql +rspec mysql 3 20: *rspec-knapsack-mysql +rspec mysql 4 20: *rspec-knapsack-mysql +rspec mysql 5 20: *rspec-knapsack-mysql +rspec mysql 6 20: *rspec-knapsack-mysql +rspec mysql 7 20: *rspec-knapsack-mysql +rspec mysql 8 20: *rspec-knapsack-mysql +rspec mysql 9 20: *rspec-knapsack-mysql +rspec mysql 10 20: *rspec-knapsack-mysql +rspec mysql 11 20: *rspec-knapsack-mysql +rspec mysql 12 20: *rspec-knapsack-mysql +rspec mysql 13 20: *rspec-knapsack-mysql +rspec mysql 14 20: *rspec-knapsack-mysql +rspec mysql 15 20: *rspec-knapsack-mysql +rspec mysql 16 20: *rspec-knapsack-mysql +rspec mysql 17 20: *rspec-knapsack-mysql +rspec mysql 18 20: *rspec-knapsack-mysql +rspec mysql 19 20: *rspec-knapsack-mysql + +spinach pg 0 10: *spinach-knapsack-pg +spinach pg 1 10: *spinach-knapsack-pg +spinach pg 2 10: *spinach-knapsack-pg +spinach pg 3 10: *spinach-knapsack-pg +spinach pg 4 10: *spinach-knapsack-pg +spinach pg 5 10: *spinach-knapsack-pg +spinach pg 6 10: *spinach-knapsack-pg +spinach pg 7 10: *spinach-knapsack-pg +spinach pg 8 10: *spinach-knapsack-pg +spinach pg 9 10: *spinach-knapsack-pg + +spinach mysql 0 10: *spinach-knapsack-mysql +spinach mysql 1 10: *spinach-knapsack-mysql +spinach mysql 2 10: *spinach-knapsack-mysql +spinach mysql 3 10: *spinach-knapsack-mysql +spinach mysql 4 10: *spinach-knapsack-mysql +spinach mysql 5 10: *spinach-knapsack-mysql +spinach mysql 6 10: *spinach-knapsack-mysql +spinach mysql 7 10: *spinach-knapsack-mysql +spinach mysql 8 10: *spinach-knapsack-mysql +spinach mysql 9 10: *spinach-knapsack-mysql # Other generic tests .ruby-static-analysis: &ruby-static-analysis @@ -228,24 +286,37 @@ rake ee_compat_check: paths: - ee_compat_check/patches/*.patch -rake db:migrate:reset: +.db-migrate-reset: &db-migrate-reset stage: test - <<: *use-db <<: *dedicated-runner script: - bundle exec rake db:migrate:reset -rake db:rollback: +rake pg db:migrate:reset: + <<: *db-migrate-reset + <<: *use-pg + +rake mysql db:migrate:reset: + <<: *db-migrate-reset + <<: *use-mysql + +.db-rollback: &db-rollback stage: test - <<: *use-db <<: *dedicated-runner script: - bundle exec rake db:rollback STEP=120 - bundle exec rake db:migrate -rake db:seed_fu: +rake pg db:rollback: + <<: *db-rollback + <<: *use-pg + +rake mysql db:rollback: + <<: *db-rollback + <<: *use-mysql + +.db-seed_fu: &db-seed_fu stage: test - <<: *use-db <<: *dedicated-runner variables: SIZE: "1" @@ -261,6 +332,14 @@ rake db:seed_fu: paths: - log/development.log +rake pg db:seed_fu: + <<: *db-seed_fu + <<: *use-pg + +rake mysql db:seed_fu: + <<: *db-seed_fu + <<: *use-mysql + rake gitlab:assets:compile: stage: test <<: *dedicated-runner @@ -285,7 +364,7 @@ rake karma: paths: - vendor/ruby stage: test - <<: *use-db + <<: *use-pg <<: *dedicated-runner variables: BABEL_ENV: "coverage" @@ -342,9 +421,8 @@ bundler:audit: script: - "bundle exec bundle-audit check --update --ignore CVE-2016-4658" -migration paths: +.migration-paths: &migration-paths stage: test - <<: *use-db <<: *dedicated-runner variables: SETUP_DB: "false" @@ -356,13 +434,21 @@ migration paths: script: - git fetch origin v8.14.10 - git checkout -f FETCH_HEAD - - bundle install --without postgres production --jobs $(nproc) $FLAGS --retry=3 + - bundle install $BUNDLE_INSTALL_FLAGS - bundle exec rake db:drop db:create db:schema:load db:seed_fu - git checkout $CI_COMMIT_SHA - - bundle install --without postgres production --jobs $(nproc) $FLAGS --retry=3 - - source scripts/prepare_build.sh + - bundle install $BUNDLE_INSTALL_FLAGS + - . scripts/prepare_build.sh - bundle exec rake db:migrate +migration pg paths: + <<: *migration-paths + <<: *use-pg + +migration mysql paths: + <<: *migration-paths + <<: *use-mysql + coverage: stage: post-test services: [] @@ -409,7 +495,7 @@ trigger_docs: before_script: - apk update && apk add curl variables: - GIT_STRATEGY: none + GIT_STRATEGY: "none" cache: {} artifacts: {} script: diff --git a/README.md b/README.md index f0e3b52ef6f..10d69efdc6b 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ One small thing you also have to do when installing it yourself is to copy the e cp config/unicorn.rb.example.development config/unicorn.rb -Instructions on how to start GitLab and how to run the tests can be found in the [development section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#development). +Instructions on how to start GitLab and how to run the tests can be found in the [getting started section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#getting-started). ## Software stack diff --git a/app/assets/javascripts/blob/notebook/index.js b/app/assets/javascripts/blob/notebook/index.js index 9b8bfbfc8c0..36fe8a7184f 100644 --- a/app/assets/javascripts/blob/notebook/index.js +++ b/app/assets/javascripts/blob/notebook/index.js @@ -1,10 +1,9 @@ /* eslint-disable no-new */ import Vue from 'vue'; import VueResource from 'vue-resource'; -import NotebookLab from 'vendor/notebooklab'; +import notebookLab from '../../notebook/index.vue'; Vue.use(VueResource); -Vue.use(NotebookLab); export default () => { const el = document.getElementById('js-notebook-viewer'); @@ -19,6 +18,9 @@ export default () => { json: {}, }; }, + components: { + notebookLab, + }, template: ` <div class="container-fluid md prepend-top-default append-bottom-default"> <div diff --git a/app/assets/javascripts/notebook/cells/code.vue b/app/assets/javascripts/notebook/cells/code.vue new file mode 100644 index 00000000000..b8a16356576 --- /dev/null +++ b/app/assets/javascripts/notebook/cells/code.vue @@ -0,0 +1,58 @@ +<template> + <div class="cell"> + <code-cell + type="input" + :raw-code="rawInputCode" + :count="cell.execution_count" + :code-css-class="codeCssClass" /> + <output-cell + v-if="hasOutput" + :count="cell.execution_count" + :output="output" + :code-css-class="codeCssClass" /> + </div> +</template> + +<script> +import CodeCell from './code/index.vue'; +import OutputCell from './output/index.vue'; + +export default { + components: { + 'code-cell': CodeCell, + 'output-cell': OutputCell, + }, + props: { + cell: { + type: Object, + required: true, + }, + codeCssClass: { + type: String, + required: false, + default: '', + }, + }, + computed: { + rawInputCode() { + if (this.cell.source) { + return this.cell.source.join(''); + } + + return ''; + }, + hasOutput() { + return this.cell.outputs.length; + }, + output() { + return this.cell.outputs[0]; + }, + }, +}; +</script> + +<style scoped> +.cell { + flex-direction: column; +} +</style> diff --git a/app/assets/javascripts/notebook/cells/code/index.vue b/app/assets/javascripts/notebook/cells/code/index.vue new file mode 100644 index 00000000000..31b30f601e2 --- /dev/null +++ b/app/assets/javascripts/notebook/cells/code/index.vue @@ -0,0 +1,57 @@ +<template> + <div :class="type"> + <prompt + :type="promptType" + :count="count" /> + <pre + class="language-python" + :class="codeCssClass" + ref="code" + v-text="code"> + </pre> + </div> +</template> + +<script> + import Prism from '../../lib/highlight'; + import Prompt from '../prompt.vue'; + + export default { + components: { + prompt: Prompt, + }, + props: { + count: { + type: Number, + required: false, + default: 0, + }, + codeCssClass: { + type: String, + required: false, + default: '', + }, + type: { + type: String, + required: true, + }, + rawCode: { + type: String, + required: true, + }, + }, + computed: { + code() { + return this.rawCode; + }, + promptType() { + const type = this.type.split('put')[0]; + + return type.charAt(0).toUpperCase() + type.slice(1); + }, + }, + mounted() { + Prism.highlightElement(this.$refs.code); + }, + }; +</script> diff --git a/app/assets/javascripts/notebook/cells/index.js b/app/assets/javascripts/notebook/cells/index.js new file mode 100644 index 00000000000..e4c255609fe --- /dev/null +++ b/app/assets/javascripts/notebook/cells/index.js @@ -0,0 +1,2 @@ +export { default as MarkdownCell } from './markdown.vue'; +export { default as CodeCell } from './code.vue'; diff --git a/app/assets/javascripts/notebook/cells/markdown.vue b/app/assets/javascripts/notebook/cells/markdown.vue new file mode 100644 index 00000000000..3e8240d10ec --- /dev/null +++ b/app/assets/javascripts/notebook/cells/markdown.vue @@ -0,0 +1,98 @@ +<template> + <div class="cell text-cell"> + <prompt /> + <div class="markdown" v-html="markdown"></div> + </div> +</template> + +<script> + /* global katex */ + import marked from 'marked'; + import Prompt from './prompt.vue'; + + const renderer = new marked.Renderer(); + + /* + Regex to match KaTex blocks. + + Supports the following: + + \begin{equation}<math>\end{equation} + $$<math>$$ + inline $<math>$ + + The matched text then goes through the KaTex renderer & then outputs the HTML + */ + const katexRegexString = `( + ^\\\\begin{[a-zA-Z]+}\\s + | + ^\\$\\$ + | + \\s\\$(?!\\$) + ) + (.+?) + ( + \\s\\\\end{[a-zA-Z]+}$ + | + \\$\\$$ + | + \\$ + ) + `.replace(/\s/g, '').trim(); + + renderer.paragraph = (t) => { + let text = t; + let inline = false; + + if (typeof katex !== 'undefined') { + const katexString = text.replace(/\\/g, '\\'); + const matches = new RegExp(katexRegexString, 'gi').exec(katexString); + + if (matches && matches.length > 0) { + if (matches[1].trim() === '$' && matches[3].trim() === '$') { + inline = true; + + text = `${katexString.replace(matches[0], '')} ${katex.renderToString(matches[2])}`; + } else { + text = katex.renderToString(matches[2]); + } + } + } + + return `<p class="${inline ? 'inline-katex' : ''}">${text}</p>`; + }; + + marked.setOptions({ + sanitize: true, + renderer, + }); + + export default { + components: { + prompt: Prompt, + }, + props: { + cell: { + type: Object, + required: true, + }, + }, + computed: { + markdown() { + return marked(this.cell.source.join('')); + }, + }, + }; +</script> + +<style> +.markdown .katex { + display: block; + text-align: center; +} + +.markdown .inline-katex .katex { + display: inline; + text-align: initial; +} +</style> diff --git a/app/assets/javascripts/notebook/cells/output/html.vue b/app/assets/javascripts/notebook/cells/output/html.vue new file mode 100644 index 00000000000..0f39cd138df --- /dev/null +++ b/app/assets/javascripts/notebook/cells/output/html.vue @@ -0,0 +1,22 @@ +<template> + <div class="output"> + <prompt /> + <div v-html="rawCode"></div> + </div> +</template> + +<script> +import Prompt from '../prompt.vue'; + +export default { + props: { + rawCode: { + type: String, + required: true, + }, + }, + components: { + prompt: Prompt, + }, +}; +</script> diff --git a/app/assets/javascripts/notebook/cells/output/image.vue b/app/assets/javascripts/notebook/cells/output/image.vue new file mode 100644 index 00000000000..f3b873bbc0f --- /dev/null +++ b/app/assets/javascripts/notebook/cells/output/image.vue @@ -0,0 +1,27 @@ +<template> + <div class="output"> + <prompt /> + <img + :src="'data:' + outputType + ';base64,' + rawCode" /> + </div> +</template> + +<script> +import Prompt from '../prompt.vue'; + +export default { + props: { + outputType: { + type: String, + required: true, + }, + rawCode: { + type: String, + required: true, + }, + }, + components: { + prompt: Prompt, + }, +}; +</script> diff --git a/app/assets/javascripts/notebook/cells/output/index.vue b/app/assets/javascripts/notebook/cells/output/index.vue new file mode 100644 index 00000000000..23c9ea78939 --- /dev/null +++ b/app/assets/javascripts/notebook/cells/output/index.vue @@ -0,0 +1,83 @@ +<template> + <component :is="componentName" + type="output" + :outputType="outputType" + :count="count" + :raw-code="rawCode" + :code-css-class="codeCssClass" /> +</template> + +<script> +import CodeCell from '../code/index.vue'; +import Html from './html.vue'; +import Image from './image.vue'; + +export default { + props: { + codeCssClass: { + type: String, + required: false, + default: '', + }, + count: { + type: Number, + required: false, + default: 0, + }, + output: { + type: Object, + requred: true, + }, + }, + components: { + 'code-cell': CodeCell, + 'html-output': Html, + 'image-output': Image, + }, + data() { + return { + outputType: '', + }; + }, + computed: { + componentName() { + if (this.output.text) { + return 'code-cell'; + } else if (this.output.data['image/png']) { + this.outputType = 'image/png'; + + return 'image-output'; + } else if (this.output.data['text/html']) { + this.outputType = 'text/html'; + + return 'html-output'; + } else if (this.output.data['image/svg+xml']) { + this.outputType = 'image/svg+xml'; + + return 'html-output'; + } + + this.outputType = 'text/plain'; + return 'code-cell'; + }, + rawCode() { + if (this.output.text) { + return this.output.text.join(''); + } + + return this.dataForType(this.outputType); + }, + }, + methods: { + dataForType(type) { + let data = this.output.data[type]; + + if (typeof data === 'object') { + data = data.join(''); + } + + return data; + }, + }, +}; +</script> diff --git a/app/assets/javascripts/notebook/cells/prompt.vue b/app/assets/javascripts/notebook/cells/prompt.vue new file mode 100644 index 00000000000..4540e4248d8 --- /dev/null +++ b/app/assets/javascripts/notebook/cells/prompt.vue @@ -0,0 +1,30 @@ +<template> + <div class="prompt"> + <span v-if="type && count"> + {{ type }} [{{ count }}]: + </span> + </div> +</template> + +<script> + export default { + props: { + type: { + type: String, + required: false, + }, + count: { + type: Number, + required: false, + }, + }, + }; +</script> + +<style scoped> +.prompt { + padding: 0 10px; + min-width: 7em; + font-family: monospace; +} +</style> diff --git a/app/assets/javascripts/notebook/index.vue b/app/assets/javascripts/notebook/index.vue new file mode 100644 index 00000000000..fd62c1231ef --- /dev/null +++ b/app/assets/javascripts/notebook/index.vue @@ -0,0 +1,75 @@ +<template> + <div v-if="hasNotebook"> + <component + v-for="(cell, index) in cells" + :is="cellType(cell.cell_type)" + :cell="cell" + :key="index" + :code-css-class="codeCssClass" /> + </div> +</template> + +<script> + import { + MarkdownCell, + CodeCell, + } from './cells'; + + export default { + components: { + 'code-cell': CodeCell, + 'markdown-cell': MarkdownCell, + }, + props: { + notebook: { + type: Object, + required: true, + }, + codeCssClass: { + type: String, + required: false, + default: '', + }, + }, + methods: { + cellType(type) { + return `${type}-cell`; + }, + }, + computed: { + cells() { + if (this.notebook.worksheets) { + const data = { + cells: [], + }; + + return this.notebook.worksheets.reduce((cellData, sheet) => { + const cellDataCopy = cellData; + cellDataCopy.cells = cellDataCopy.cells.concat(sheet.cells); + return cellDataCopy; + }, data).cells; + } + + return this.notebook.cells; + }, + hasNotebook() { + return Object.keys(this.notebook).length; + }, + }, + }; +</script> + +<style> +.cell, +.input, +.output { + display: flex; + width: 100%; + margin-bottom: 10px; +} + +.cell pre { + margin: 0; + width: 100%; +} +</style> diff --git a/app/assets/javascripts/notebook/lib/highlight.js b/app/assets/javascripts/notebook/lib/highlight.js new file mode 100644 index 00000000000..74ade6d2edf --- /dev/null +++ b/app/assets/javascripts/notebook/lib/highlight.js @@ -0,0 +1,22 @@ +import Prism from 'prismjs'; +import 'prismjs/components/prism-python'; +import 'prismjs/plugins/custom-class/prism-custom-class'; + +Prism.plugins.customClass.map({ + comment: 'c', + error: 'err', + operator: 'o', + constant: 'kc', + namespace: 'kn', + keyword: 'k', + string: 's', + number: 'm', + 'attr-name': 'na', + builtin: 'nb', + entity: 'ni', + function: 'nf', + tag: 'nt', + variable: 'nv', +}); + +export default Prism; diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index 52425262925..f3e2a5db0a6 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -230,7 +230,6 @@ float: right; margin-top: 8px; padding-bottom: 8px; - border-bottom: 1px solid $border-color; } } diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index e6d808717f3..b6cf5101d60 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -110,7 +110,7 @@ .top-area { @include clearfix; - border-bottom: 1px solid $white-normal; + border-bottom: 1px solid $border-color; .nav-text { padding-top: 16px; diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index b637994adf8..03d1c3067c7 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -387,6 +387,7 @@ @media (max-width: $screen-xs-max) { display: flex; width: 100%; + margin-bottom: 10px; .comment-btn { flex-grow: 1; diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 2ea2ff8362b..98b93cca6e3 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -386,6 +386,10 @@ ul.notes { .note-headline-meta { display: inline-block; white-space: nowrap; + + .system-note-message { + white-space: normal; + } } /** diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 408c0c60cb0..d0dd524c484 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -23,6 +23,7 @@ class Projects::MilestonesController < Projects::ApplicationController respond_to do |format| format.html do + @project_namespace = @project.namespace.becomes(Namespace) @milestones = @milestones.includes(:project) @milestones = @milestones.page(params[:page]) end diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 2de9e0de310..32b1e7822af 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -1,10 +1,16 @@ +## +# DEPRECATED +# +# These helpers are deprecated in favor of detailed CI/CD statuses. +# +# See 'detailed_status?` method and `Gitlab::Ci::Status` module. +# module CiStatusHelper def ci_status_path(pipeline) project = pipeline.project namespace_project_pipeline_path(project.namespace, project, pipeline) end - # Is used by Commit and Merge Request Widget def ci_label_for_status(status) if detailed_status?(status) return status.label @@ -22,6 +28,23 @@ module CiStatusHelper end end + def ci_text_for_status(status) + if detailed_status?(status) + return status.text + end + + case status + when 'success' + 'passed' + when 'success_with_warnings' + 'passed' + when 'manual' + 'blocked' + else + status + end + end + def ci_status_for_statuseable(subject) status = subject.try(:status) || 'not found' status.humanize diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 445247f1b41..4be4aa9ffe2 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -75,29 +75,32 @@ module Ci pipeline.update_duration end + before_transition any => [:manual] do |pipeline| + pipeline.update_duration + end + before_transition canceled: any - [:canceled] do |pipeline| pipeline.auto_canceled_by = nil end after_transition [:created, :pending] => :running do |pipeline| - pipeline.run_after_commit { PipelineMetricsWorker.perform_async(id) } + pipeline.run_after_commit { PipelineMetricsWorker.perform_async(pipeline.id) } end after_transition any => [:success] do |pipeline| - pipeline.run_after_commit { PipelineMetricsWorker.perform_async(id) } + pipeline.run_after_commit { PipelineMetricsWorker.perform_async(pipeline.id) } end after_transition [:created, :pending, :running] => :success do |pipeline| - pipeline.run_after_commit { PipelineSuccessWorker.perform_async(id) } + pipeline.run_after_commit { PipelineSuccessWorker.perform_async(pipeline.id) } end after_transition do |pipeline, transition| next if transition.loopback? pipeline.run_after_commit do - PipelineHooksWorker.perform_async(id) - Ci::ExpirePipelineCacheService.new(project, nil) - .execute(pipeline) + PipelineHooksWorker.perform_async(pipeline.id) + ExpirePipelineCacheWorker.perform_async(pipeline.id) end end @@ -385,6 +388,11 @@ module Ci .select { |merge_request| merge_request.head_pipeline.try(:id) == self.id } end + # All the merge requests for which the current pipeline runs/ran against + def all_merge_requests + @all_merge_requests ||= project.merge_requests.where(source_branch: ref) + end + def detailed_status(current_user) Gitlab::Ci::Status::Pipeline::Factory .new(self, current_user) diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb index aca99feee53..b28e05d0c28 100644 --- a/app/models/concerns/routable.rb +++ b/app/models/concerns/routable.rb @@ -163,7 +163,20 @@ module Routable end end + # Every time `project.namespace.becomes(Namespace)` is called for polymorphic_path, + # a new instance is instantiated, and we end up duplicating the same query to retrieve + # the route. Caching this per request ensures that even if we have multiple instances, + # we will not have to duplicate work, avoiding N+1 queries in some cases. def full_path + return uncached_full_path unless RequestStore.active? + + key = "routable/full_path/#{self.class.name}/#{self.id}" + RequestStore[key] ||= uncached_full_path + end + + private + + def uncached_full_path if route && route.path.present? @full_path ||= route.path else @@ -173,8 +186,6 @@ module Routable end end - private - def full_name_changed? name_changed? || parent_changed? end diff --git a/app/services/ci/expire_pipeline_cache_service.rb b/app/services/ci/expire_pipeline_cache_service.rb deleted file mode 100644 index 91d9c1d2ba1..00000000000 --- a/app/services/ci/expire_pipeline_cache_service.rb +++ /dev/null @@ -1,51 +0,0 @@ -module Ci - class ExpirePipelineCacheService < BaseService - attr_reader :pipeline - - def execute(pipeline) - @pipeline = pipeline - store = Gitlab::EtagCaching::Store.new - - store.touch(project_pipelines_path) - store.touch(commit_pipelines_path) if pipeline.commit - store.touch(new_merge_request_pipelines_path) - merge_requests_pipelines_paths.each { |path| store.touch(path) } - - Gitlab::Cache::Ci::ProjectPipelineStatus.update_for_pipeline(@pipeline) - end - - private - - def project_pipelines_path - Gitlab::Routing.url_helpers.namespace_project_pipelines_path( - project.namespace, - project, - format: :json) - end - - def commit_pipelines_path - Gitlab::Routing.url_helpers.pipelines_namespace_project_commit_path( - project.namespace, - project, - pipeline.commit.id, - format: :json) - end - - def new_merge_request_pipelines_path - Gitlab::Routing.url_helpers.new_namespace_project_merge_request_path( - project.namespace, - project, - format: :json) - end - - def merge_requests_pipelines_paths - pipeline.merge_requests.collect do |merge_request| - Gitlab::Routing.url_helpers.pipelines_namespace_project_merge_request_path( - project.namespace, - project, - merge_request, - format: :json) - end - end - end -end diff --git a/app/services/users/migrate_to_ghost_user_service.rb b/app/services/users/migrate_to_ghost_user_service.rb index 1e1ed1791ec..4628c4c6f6e 100644 --- a/app/services/users/migrate_to_ghost_user_service.rb +++ b/app/services/users/migrate_to_ghost_user_service.rb @@ -15,27 +15,39 @@ module Users end def execute - # Block the user before moving records to prevent a data race. - # For example, if the user creates an issue after `migrate_issues` - # runs and before the user is destroyed, the destroy will fail with - # an exception. - user.block + transition = user.block_transition user.transaction do + # Block the user before moving records to prevent a data race. + # For example, if the user creates an issue after `migrate_issues` + # runs and before the user is destroyed, the destroy will fail with + # an exception. + user.block + + # Reverse the user block if record migration fails + if !migrate_records && transition + transition.rollback + user.save! + end + end + + user.reload + end + + private + + def migrate_records + user.transaction(requires_new: true) do @ghost_user = User.ghost migrate_issues migrate_merge_requests migrate_notes migrate_abuse_reports - migrate_award_emoji + migrate_award_emojis end - - user.reload end - private - def migrate_issues user.issues.update_all(author_id: ghost_user.id) end @@ -52,7 +64,7 @@ module Users user.reported_abuse_reports.update_all(reporter_id: ghost_user.id) end - def migrate_award_emoji + def migrate_award_emojis user.award_emoji.update_all(user_id: ghost_user.id) end end diff --git a/app/views/projects/_last_commit.html.haml b/app/views/projects/_last_commit.html.haml index e1fea8ccf3d..df3b1c75508 100644 --- a/app/views/projects/_last_commit.html.haml +++ b/app/views/projects/_last_commit.html.haml @@ -1,10 +1,9 @@ - - ref = local_assigns.fetch(:ref) - status = commit.status(ref) - if status = link_to pipelines_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do = ci_icon_for_status(status) - = ci_label_for_status(status) + = ci_text_for_status(status) = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id" = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message" diff --git a/app/views/shared/milestones/_issuable.html.haml b/app/views/shared/milestones/_issuable.html.haml index 4c7d69d40d5..5247d6a51e6 100644 --- a/app/views/shared/milestones/_issuable.html.haml +++ b/app/views/shared/milestones/_issuable.html.haml @@ -1,11 +1,14 @@ -# @project is present when viewing Project's milestone - project = @project || issuable.project +- namespace = @project_namespace || project.namespace.becomes(Namespace) - assignee = issuable.assignee - issuable_type = issuable.class.table_name -- base_url_args = [project.namespace.becomes(Namespace), project, issuable_type] +- base_url_args = [namespace, project] +- issuable_type_args = base_url_args + [issuable_type] +- issuable_url_args = base_url_args + [issuable] - can_update = can?(current_user, :"update_#{issuable.to_ability_name}", issuable) -%li{ id: dom_id(issuable, 'sortable'), class: "issuable-row #{'is-disabled' unless can_update}", 'data-iid' => issuable.iid, 'data-id' => issuable.id, 'data-url' => polymorphic_path(issuable) } +%li{ id: dom_id(issuable, 'sortable'), class: "issuable-row #{'is-disabled' unless can_update}", 'data-iid' => issuable.iid, 'data-id' => issuable.id, 'data-url' => polymorphic_path(issuable_url_args) } %span - if show_project_name %strong #{project.name} · @@ -13,17 +16,17 @@ %strong #{project.name_with_namespace} · - if issuable.is_a?(Issue) = confidential_icon(issuable) - = link_to_gfm issuable.title, [project.namespace.becomes(Namespace), project, issuable], title: issuable.title + = link_to_gfm issuable.title, issuable_url_args, title: issuable.title .issuable-detail = link_to [project.namespace.becomes(Namespace), project, issuable] do %span.issuable-number= issuable.to_reference - issuable.labels.each do |label| - = link_to polymorphic_path(base_url_args, { milestone_title: @milestone.title, label_name: label.title, state: 'all' }) do + = link_to polymorphic_path(issuable_type_args, { milestone_title: @milestone.title, label_name: label.title, state: 'all' }) do - render_colored_label(label) %span.assignee-icon - if assignee - = link_to polymorphic_path(base_url_args, { milestone_title: @milestone.title, assignee_id: issuable.assignee_id, state: 'all' }), + = link_to polymorphic_path(issuable_type_args, { milestone_title: @milestone.title, assignee_id: issuable.assignee_id, state: 'all' }), class: 'has-tooltip', title: "Assigned to #{assignee.name}", data: { container: 'body' } do - image_tag(avatar_icon(issuable.assignee, 16), class: "avatar s16", alt: '') diff --git a/app/workers/expire_pipeline_cache_worker.rb b/app/workers/expire_pipeline_cache_worker.rb new file mode 100644 index 00000000000..603e2f1aaea --- /dev/null +++ b/app/workers/expire_pipeline_cache_worker.rb @@ -0,0 +1,57 @@ +class ExpirePipelineCacheWorker + include Sidekiq::Worker + include PipelineQueue + + def perform(pipeline_id) + pipeline = Ci::Pipeline.find_by(id: pipeline_id) + return unless pipeline + + project = pipeline.project + store = Gitlab::EtagCaching::Store.new + + store.touch(project_pipelines_path(project)) + store.touch(commit_pipelines_path(project, pipeline.commit)) if pipeline.commit + store.touch(new_merge_request_pipelines_path(project)) + each_pipelines_merge_request_path(project, pipeline) do |path| + store.touch(path) + end + + Gitlab::Cache::Ci::ProjectPipelineStatus.update_for_pipeline(pipeline) + end + + private + + def project_pipelines_path(project) + Gitlab::Routing.url_helpers.namespace_project_pipelines_path( + project.namespace, + project, + format: :json) + end + + def commit_pipelines_path(project, commit) + Gitlab::Routing.url_helpers.pipelines_namespace_project_commit_path( + project.namespace, + project, + commit.id, + format: :json) + end + + def new_merge_request_pipelines_path(project) + Gitlab::Routing.url_helpers.new_namespace_project_merge_request_path( + project.namespace, + project, + format: :json) + end + + def each_pipelines_merge_request_path(project, pipeline) + pipeline.all_merge_requests.each do |merge_request| + path = Gitlab::Routing.url_helpers.pipelines_namespace_project_merge_request_path( + project.namespace, + project, + merge_request, + format: :json) + + yield(path) + end + end +end diff --git a/changelogs/unreleased/1440-db-backup-ssl-support.yml b/changelogs/unreleased/1440-db-backup-ssl-support.yml new file mode 100644 index 00000000000..c78bb4fd351 --- /dev/null +++ b/changelogs/unreleased/1440-db-backup-ssl-support.yml @@ -0,0 +1,4 @@ +--- +title: Database SSL support for backup script. +merge_request: 9715 +author: Guillaume Simon diff --git a/changelogs/unreleased/29712-unnecessary-wait-for-ajax.yml b/changelogs/unreleased/29712-unnecessary-wait-for-ajax.yml new file mode 100644 index 00000000000..8dc657a4aba --- /dev/null +++ b/changelogs/unreleased/29712-unnecessary-wait-for-ajax.yml @@ -0,0 +1,4 @@ +--- +title: Remove unnecessary test helpers includes +merge_request: 10567 +author: Jacopo Beschi @jacopo-beschi diff --git a/changelogs/unreleased/29801-add-slash-slack-commands-to-api-doc.yml b/changelogs/unreleased/29801-add-slash-slack-commands-to-api-doc.yml new file mode 100644 index 00000000000..9c5df690085 --- /dev/null +++ b/changelogs/unreleased/29801-add-slash-slack-commands-to-api-doc.yml @@ -0,0 +1,5 @@ +--- +title: Add Slack slash command api to services documentation and rearrange order and + cases +merge_request: 10757 +author: TM Lee diff --git a/changelogs/unreleased/30305-oauth-token-push-code.yml b/changelogs/unreleased/30305-oauth-token-push-code.yml new file mode 100644 index 00000000000..aadfb5ca419 --- /dev/null +++ b/changelogs/unreleased/30305-oauth-token-push-code.yml @@ -0,0 +1,4 @@ +--- +title: Allow OAuth clients to push code +merge_request: 10677 +author: diff --git a/changelogs/unreleased/30306-transaction-while-moving-issues-to-ghost-user.yml b/changelogs/unreleased/30306-transaction-while-moving-issues-to-ghost-user.yml new file mode 100644 index 00000000000..5fc57e44be6 --- /dev/null +++ b/changelogs/unreleased/30306-transaction-while-moving-issues-to-ghost-user.yml @@ -0,0 +1,4 @@ +--- +title: Add a transaction around move_issues_to_ghost_user +merge_request: 10465 +author: diff --git a/changelogs/unreleased/add_index_on_ci_builds_updated_at.yml b/changelogs/unreleased/add_index_on_ci_builds_updated_at.yml new file mode 100644 index 00000000000..ede9b946a70 --- /dev/null +++ b/changelogs/unreleased/add_index_on_ci_builds_updated_at.yml @@ -0,0 +1,4 @@ +--- +title: Add index on ci_builds.updated_at +merge_request: 10870 +author: blackst0ne diff --git a/changelogs/unreleased/diff-discussion-buttons-spacing.yml b/changelogs/unreleased/diff-discussion-buttons-spacing.yml new file mode 100644 index 00000000000..dc76973e55b --- /dev/null +++ b/changelogs/unreleased/diff-discussion-buttons-spacing.yml @@ -0,0 +1,4 @@ +--- +title: Fixed spacing of discussion submit buttons +merge_request: +author: diff --git a/changelogs/unreleased/dm-fix-position-tracer-for-hidden-lines.yml b/changelogs/unreleased/dm-fix-position-tracer-for-hidden-lines.yml new file mode 100644 index 00000000000..d9ba26a0657 --- /dev/null +++ b/changelogs/unreleased/dm-fix-position-tracer-for-hidden-lines.yml @@ -0,0 +1,5 @@ +--- +title: Fix commenting on an existing discussion on an unchanged line that is no longer + in the diff +merge_request: +author: diff --git a/changelogs/unreleased/fix-gb-fix-blocked-pipeline-duration.yml b/changelogs/unreleased/fix-gb-fix-blocked-pipeline-duration.yml new file mode 100644 index 00000000000..5c87b1fdbd5 --- /dev/null +++ b/changelogs/unreleased/fix-gb-fix-blocked-pipeline-duration.yml @@ -0,0 +1,4 @@ +--- +title: Fix missing duration for blocked pipelines +merge_request: 10856 +author: diff --git a/changelogs/unreleased/fix-gb-fix-incorrect-commit-status-badge-text.yml b/changelogs/unreleased/fix-gb-fix-incorrect-commit-status-badge-text.yml new file mode 100644 index 00000000000..abe047af06f --- /dev/null +++ b/changelogs/unreleased/fix-gb-fix-incorrect-commit-status-badge-text.yml @@ -0,0 +1,4 @@ +--- +title: Fix lastest commit status text on main project page +merge_request: 10863 +author: diff --git a/changelogs/unreleased/fix_link_in_readme.yml b/changelogs/unreleased/fix_link_in_readme.yml new file mode 100644 index 00000000000..be5ceac8656 --- /dev/null +++ b/changelogs/unreleased/fix_link_in_readme.yml @@ -0,0 +1,4 @@ +--- +title: Fix dead link to GDK on the README page +merge_request: +author: Dino Maric diff --git a/changelogs/unreleased/mrchrisw-22740-merge-api.yml b/changelogs/unreleased/mrchrisw-22740-merge-api.yml new file mode 100644 index 00000000000..e75160aec70 --- /dev/null +++ b/changelogs/unreleased/mrchrisw-22740-merge-api.yml @@ -0,0 +1,4 @@ +--- +title: Fix updating merge_when_build_succeeds via merge API endpoint +merge_request: 10873 +author: diff --git a/changelogs/unreleased/sh-optimize-duplicate-routable-full-path.yml b/changelogs/unreleased/sh-optimize-duplicate-routable-full-path.yml new file mode 100644 index 00000000000..b1ef00f09b2 --- /dev/null +++ b/changelogs/unreleased/sh-optimize-duplicate-routable-full-path.yml @@ -0,0 +1,4 @@ +--- +title: Cache Routable#full_path in RequestStore to reduce duplicate route loads +merge_request: +author: diff --git a/changelogs/unreleased/sh-optimize-milestone-polymorphic-url.yml b/changelogs/unreleased/sh-optimize-milestone-polymorphic-url.yml new file mode 100644 index 00000000000..ad62c896b04 --- /dev/null +++ b/changelogs/unreleased/sh-optimize-milestone-polymorphic-url.yml @@ -0,0 +1,4 @@ +--- +title: Eliminate N+1 queries in loading namespaces for every issuable in milestones +merge_request: +author: diff --git a/changelogs/unreleased/tc-realtime-every-pipeline-on-mr.yml b/changelogs/unreleased/tc-realtime-every-pipeline-on-mr.yml new file mode 100644 index 00000000000..944baae257c --- /dev/null +++ b/changelogs/unreleased/tc-realtime-every-pipeline-on-mr.yml @@ -0,0 +1,4 @@ +--- +title: Properly expire cache for all MRs of a pipeline +merge_request: 10770 +author: diff --git a/config/database.yml.mysql b/config/database.yml.mysql index a33e40e8eb3..db1b712d3bc 100644 --- a/config/database.yml.mysql +++ b/config/database.yml.mysql @@ -25,6 +25,7 @@ development: pool: 5 username: root password: "secure password" + # host: localhost # socket: /tmp/mysql.sock # Warning: The database defined as "test" will be erased and @@ -39,4 +40,5 @@ test: &test pool: 5 username: root password: + # host: localhost # socket: /tmp/mysql.sock diff --git a/config/database.yml.postgresql b/config/database.yml.postgresql index 7067e0fe402..c517a4c0cb8 100644 --- a/config/database.yml.postgresql +++ b/config/database.yml.postgresql @@ -9,7 +9,7 @@ production: # username: git # password: # host: localhost - # port: 5432 + # port: 5432 # # Development specific @@ -21,6 +21,7 @@ development: pool: 5 username: postgres password: + # host: localhost # # Staging specific @@ -32,6 +33,7 @@ staging: pool: 5 username: postgres password: + # host: localhost # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". @@ -43,3 +45,4 @@ test: &test pool: 5 username: postgres password: + # host: localhost diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 06c9f734c2a..c2eaf263937 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -505,6 +505,11 @@ production: &base # If you use non-standard ssh port you need to specify it # ssh_port: 22 + workhorse: + # File that contains the secret key for verifying access for gitlab-workhorse. + # Default is '.gitlab_workhorse_secret' relative to Rails.root (i.e. root of the GitLab app). + # secret_file: /home/git/gitlab/.gitlab_workhorse_secret + ## Git settings # CAUTION! # Use the default values unless you really know what you are doing diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 87bf48a3dcd..7a8f00f11b2 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -388,6 +388,12 @@ Settings.gitlab_shell['owner_group'] ||= Settings.gitlab.user Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.__send__(:build_gitlab_shell_ssh_path_prefix) # +# Workhorse +# +Settings['workhorse'] ||= Settingslogic.new({}) +Settings.workhorse['secret_file'] ||= Rails.root.join('.gitlab_workhorse_secret') + +# # Repositories # Settings['repositories'] ||= Settingslogic.new({}) diff --git a/config/initializers/rspec_profiling.rb b/config/initializers/rspec_profiling.rb index 764c067c6f0..b909cc5b9a4 100644 --- a/config/initializers/rspec_profiling.rb +++ b/config/initializers/rspec_profiling.rb @@ -38,7 +38,7 @@ if Rails.env.test? end end - if ENV.has_key?('CI') + if ENV.has_key?('CI') && ENV['GITLAB_DATABASE'] == 'postgresql' RspecProfiling::VCS::Git.prepend(RspecProfilingExt::Git) RspecProfiling::Run.prepend(RspecProfilingExt::Run) end diff --git a/db/migrate/20170423064036_add_index_on_ci_builds_updated_at.rb b/db/migrate/20170423064036_add_index_on_ci_builds_updated_at.rb new file mode 100644 index 00000000000..0bbb74ee05e --- /dev/null +++ b/db/migrate/20170423064036_add_index_on_ci_builds_updated_at.rb @@ -0,0 +1,19 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddIndexOnCiBuildsUpdatedAt < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :ci_builds, :updated_at + end + + def down + remove_concurrent_index :ci_builds, :updated_at if index_exists?(:ci_builds, :updated_at) + end +end diff --git a/db/schema.rb b/db/schema.rb index 290d969d7de..7b13f2a98a1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170419001229) do +ActiveRecord::Schema.define(version: 20170423064036) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -241,6 +241,7 @@ ActiveRecord::Schema.define(version: 20170419001229) do add_index "ci_builds", ["status", "type", "runner_id"], name: "index_ci_builds_on_status_and_type_and_runner_id", using: :btree add_index "ci_builds", ["status"], name: "index_ci_builds_on_status", using: :btree add_index "ci_builds", ["token"], name: "index_ci_builds_on_token", unique: true, using: :btree + add_index "ci_builds", ["updated_at"], name: "index_ci_builds_on_updated_at", using: :btree create_table "ci_pipelines", force: :cascade do |t| t.string "ref" diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md index 2e22212ddde..6c6942a7bfe 100644 --- a/doc/administration/gitaly/index.md +++ b/doc/administration/gitaly/index.md @@ -1,6 +1,6 @@ # Gitaly -[Gitaly](https://gitlab.com/gitlab-org/gitlay) (introduced in GitLab +[Gitaly](https://gitlab.com/gitlab-org/gitaly) (introduced in GitLab 9.0) is a service that provides high-level RPC access to Git repositories. As of GitLab 9.1 it is still an optional component with limited scope. diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md index 5c856835039..b21817c1fd3 100644 --- a/doc/administration/integration/plantuml.md +++ b/doc/administration/integration/plantuml.md @@ -28,7 +28,7 @@ using Tomcat: sudo apt-get install tomcat7 sudo cp target/plantuml.war /var/lib/tomcat7/webapps/plantuml.war sudo chown tomcat7:tomcat7 /var/lib/tomcat7/webapps/plantuml.war -sudo service restart tomcat7 +sudo service tomcat7 restart ``` Once the Tomcat service restarts the PlantUML service will be ready and diff --git a/doc/api/jobs.md b/doc/api/jobs.md index bea2b96c97a..3f109dfdca3 100644 --- a/doc/api/jobs.md +++ b/doc/api/jobs.md @@ -120,7 +120,7 @@ Example of response Get a list of jobs for a pipeline. ``` -GET /projects/:id/pipeline/:pipeline_id/jobs +GET /projects/:id/pipelines/:pipeline_id/jobs ``` | Attribute | Type | Required | Description | diff --git a/doc/api/projects.md b/doc/api/projects.md index 63f88a464f5..51de4fef7ff 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -859,6 +859,17 @@ Parameters: | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | | `file` | string | yes | The file to be uploaded | +To upload a file from your filesystem, use the `--form` argument. This causes +cURL to post data using the header `Content-Type: multipart/form-data`. +The `file=` parameter must point to a file on your filesystem and be preceded +by `@`. For example: + +```bash +curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "file=@dk.png" https://gitlab.example.com/api/v3/projects/5/uploads +``` + +Returned object: + ```json { "alt": "dk", @@ -868,8 +879,8 @@ Parameters: ``` **Note**: The returned `url` is relative to the project path. -In Markdown contexts, the link is automatically expanded when the format in `markdown` is used. - +In Markdown contexts, the link is automatically expanded when the format in +`markdown` is used. ## Project members diff --git a/doc/api/services.md b/doc/api/services.md index 7d4779f1137..0f42c256099 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -490,41 +490,98 @@ Remove all previously JIRA settings from a project. DELETE /projects/:id/services/jira ``` -## Mattermost Slash Commands +## Slack slash commands -Ability to receive slash commands from a Mattermost chat instance. +Ability to receive slash commands from a Slack chat instance. -### Create/Edit Mattermost Slash Command service +### Get Slack slash command service settings -Set Mattermost Slash Command for a project. +Get Slack slash command service settings for a project. ``` -PUT /projects/:id/services/mattermost-slash-commands +GET /projects/:id/services/slack-slash-commands +``` + +Example response: + +```json +{ + "id": 4, + "title": "Slack slash commands", + "created_at": "2017-06-27T05:51:39-07:00", + "updated_at": "2017-06-27T05:51:39-07:00", + "active": true, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "pipeline_events": true, + "properties": { + "token": "9koXpg98eAheJpvBs5tK" + } +} +``` + +### Create/Edit Slack slash command service + +Set Slack slash command for a project. + +``` +PUT /projects/:id/services/slack-slash-commands ``` Parameters: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `token` | string | yes | The Mattermost token | +| `token` | string | yes | The Slack token | -### Delete Mattermost Slash Command service +### Delete Slack slash command service -Delete Mattermost Slash Command service for a project. +Delete Slack slash command service for a project. ``` -DELETE /projects/:id/services/mattermost-slash-commands +DELETE /projects/:id/services/slack-slash-commands ``` -### Get Mattermost Slash Command service settings +## Mattermost slash commands + +Ability to receive slash commands from a Mattermost chat instance. + +### Get Mattermost slash command service settings -Get Mattermost Slash Command service settings for a project. +Get Mattermost slash command service settings for a project. ``` GET /projects/:id/services/mattermost-slash-commands ``` +### Create/Edit Mattermost slash command service + +Set Mattermost slash command for a project. + +``` +PUT /projects/:id/services/mattermost-slash-commands +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `token` | string | yes | The Mattermost token | + + +### Delete Mattermost slash command service + +Delete Mattermost slash command service for a project. + +``` +DELETE /projects/:id/services/mattermost-slash-commands +``` + ## Pipeline-Emails Get emails for GitLab CI pipelines. diff --git a/doc/development/fe_guide/testing.md b/doc/development/fe_guide/testing.md index 66afbf4db4d..157c13352ca 100644 --- a/doc/development/fe_guide/testing.md +++ b/doc/development/fe_guide/testing.md @@ -14,8 +14,10 @@ for more information on general testing practices at GitLab. GitLab uses the [Karma][karma] test runner with [Jasmine][jasmine] as its test framework for our JavaScript unit tests. For tests that rely on DOM -manipulation we use fixtures which are pre-compiled from HAML source files and -served during testing by the [jasmine-jquery][jasmine-jquery] plugin. +manipulation, we generate HTML files using RSpec suites (see `spec/javascripts/fixtures/*.rb` for examples). +Some fixtures are still HAML templates that are translated to HTML files using the same mechanism (see `static_fixtures.rb`). +Those will be migrated over time. +Fixtures are served during testing by the [jasmine-jquery][jasmine-jquery] plugin. JavaScript tests live in `spec/javascripts/`, matching the folder structure of `app/assets/javascripts/`: `app/assets/javascripts/behaviors/autosize.js` diff --git a/doc/update/9.0-to-9.1.md b/doc/update/9.0-to-9.1.md index 1191662ee14..2d597894517 100644 --- a/doc/update/9.0-to-9.1.md +++ b/doc/update/9.0-to-9.1.md @@ -317,6 +317,17 @@ the socket path, but with `unix:` in front. Each entry under `storages:` should use the same `gitaly_address`. +#### Compile Gitaly + +This step will also create `config.toml.example` which you need below. + +```shell +cd /home/git/gitaly +sudo -u git -H git fetch --all --tags +sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION) +sudo -u git -H make +``` + #### Gitaly config.toml In GitLab 9.1 we are replacing environment variables in Gitaly with a diff --git a/features/profile/profile.feature b/features/profile/profile.feature index dc1339deb4c..70f47c97173 100644 --- a/features/profile/profile.feature +++ b/features/profile/profile.feature @@ -60,7 +60,9 @@ Feature: Profile Then I should see a password error message Scenario: I visit history tab - Given I have activity + Given I logout + And I sign in via the UI + And I have activity When I visit Audit Log page Then I should see my activity diff --git a/features/project/forked_merge_requests.feature b/features/project/forked_merge_requests.feature index 67f1e117f7f..9809b0ea0fe 100644 --- a/features/project/forked_merge_requests.feature +++ b/features/project/forked_merge_requests.feature @@ -41,8 +41,7 @@ Feature: Project Forked Merge Requests @javascript Scenario: I see the users in the target project for a new merge request - Given I logout - And I sign in as an admin + Given I sign in as an admin And I have a project forked off of "Shop" called "Forked Shop" Then I visit project "Forked Shop" merge requests page And I click link "New Merge Request" diff --git a/features/steps/project/forked_merge_requests.rb b/features/steps/project/forked_merge_requests.rb index ef1bb453615..8081b764be6 100644 --- a/features/steps/project/forked_merge_requests.rb +++ b/features/steps/project/forked_merge_requests.rb @@ -6,7 +6,7 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps include Select2Helper step 'I am a member of project "Shop"' do - @project = Project.find_by(name: "Shop") + @project = ::Project.find_by(name: "Shop") @project ||= create(:project, :repository, name: "Shop") @project.team << [@user, :reporter] end diff --git a/features/steps/project/merge_requests/acceptance.rb b/features/steps/project/merge_requests/acceptance.rb index d7167352e02..7521a9439e3 100644 --- a/features/steps/project/merge_requests/acceptance.rb +++ b/features/steps/project/merge_requests/acceptance.rb @@ -43,7 +43,7 @@ class Spinach::Features::ProjectMergeRequestsAcceptance < Spinach::FeatureSteps end step 'I am signed in as a developer of the project' do - login_as(@user) + sign_in(@user) end step 'I should see merge request merged' do diff --git a/features/steps/project/merge_requests/revert.rb b/features/steps/project/merge_requests/revert.rb index a8f4e4ef027..1149c1c2426 100644 --- a/features/steps/project/merge_requests/revert.rb +++ b/features/steps/project/merge_requests/revert.rb @@ -31,7 +31,7 @@ class Spinach::Features::RevertMergeRequests < Spinach::FeatureSteps step 'I am signed in as a developer of the project' do @user = create(:user) { |u| @project.add_developer(u) } - login_as(@user) + sign_in(@user) end step 'There is an open Merge Request' do diff --git a/features/steps/shared/authentication.rb b/features/steps/shared/authentication.rb index 5c3e724746b..97fac595d8e 100644 --- a/features/steps/shared/authentication.rb +++ b/features/steps/shared/authentication.rb @@ -1,23 +1,33 @@ -require Rails.root.join('spec', 'support', 'login_helpers') +require Rails.root.join('features', 'support', 'login_helpers') module SharedAuthentication include Spinach::DSL include LoginHelpers step 'I sign in as a user' do - login_as :user + sign_out(@user) if @user + + @user = create(:user) + sign_in(@user) + end + + step 'I sign in via the UI' do + gitlab_sign_in(create(:user)) end step 'I sign in as an admin' do - login_as :admin + sign_out(@user) if @user + + @user = create(:admin) + sign_in(@user) end step 'I sign in as "John Doe"' do - login_with(user_exists("John Doe")) + gitlab_sign_in(user_exists("John Doe")) end step 'I sign in as "Mary Jane"' do - login_with(user_exists("Mary Jane")) + gitlab_sign_in(user_exists("Mary Jane")) end step 'I should be redirected to sign in page' do @@ -25,14 +35,41 @@ module SharedAuthentication end step "I logout" do - logout + gitlab_sign_out end step "I logout directly" do - logout_direct + gitlab_sign_out end def current_user @user || User.reorder(nil).first end + + private + + def gitlab_sign_in(user) + visit new_user_session_path + + fill_in "user_login", with: user.email + fill_in "user_password", with: "12345678" + check 'user_remember_me' + click_button "Sign in" + + @user = user + end + + def gitlab_sign_out + return unless @user + + if Capybara.current_driver == Capybara.javascript_driver + find('.header-user-dropdown-toggle').click + click_link 'Sign out' + expect(page).to have_button('Sign in') + else + sign_out(@user) + end + + @user = nil + end end diff --git a/features/support/login_helpers.rb b/features/support/login_helpers.rb new file mode 100644 index 00000000000..540ff25a4f2 --- /dev/null +++ b/features/support/login_helpers.rb @@ -0,0 +1,19 @@ +module LoginHelpers + # After inclusion, IntegrationHelpers calls these two methods that aren't + # supported by Spinach, so we perform the end results ourselves + class << self + def setup(*args) + Spinach.hooks.before_scenario do + Warden.test_mode! + end + end + + def teardown(*args) + Spinach.hooks.after_scenario do + Warden.test_reset! + end + end + end + + include Devise::Test::IntegrationHelpers +end diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index cb7aec47cf0..c7dc2ea336f 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -197,14 +197,15 @@ module API end put ':id/merge_requests/:merge_request_iid/merge' do merge_request = find_project_merge_request(params[:merge_request_iid]) + merge_when_pipeline_succeeds = to_boolean(params[:merge_when_pipeline_succeeds]) # Merge request can not be merged # because user dont have permissions to push into target branch unauthorized! unless merge_request.can_be_merged_by?(current_user) - not_allowed! unless merge_request.mergeable_state? + not_allowed! unless merge_request.mergeable_state?(skip_ci_check: merge_when_pipeline_succeeds) - render_api_error!('Branch cannot be merged', 406) unless merge_request.mergeable? + render_api_error!('Branch cannot be merged', 406) unless merge_request.mergeable?(skip_ci_check: merge_when_pipeline_succeeds) if params[:sha] && merge_request.diff_head_sha != params[:sha] render_api_error!("SHA does not match HEAD of source branch: #{merge_request.diff_head_sha}", 409) @@ -215,7 +216,7 @@ module API should_remove_source_branch: params[:should_remove_source_branch] } - if params[:merge_when_pipeline_succeeds] && merge_request.head_pipeline && merge_request.head_pipeline.active? + if merge_when_pipeline_succeeds && merge_request.head_pipeline && merge_request.head_pipeline.active? ::MergeRequests::MergeWhenPipelineSucceedsService .new(merge_request.target_project, current_user, merge_params) .execute(merge_request) diff --git a/lib/backup/database.rb b/lib/backup/database.rb index 4016ac76348..d97e5d98229 100644 --- a/lib/backup/database.rb +++ b/lib/backup/database.rb @@ -80,16 +80,32 @@ module Backup 'port' => '--port', 'socket' => '--socket', 'username' => '--user', - 'encoding' => '--default-character-set' + 'encoding' => '--default-character-set', + # SSL + 'sslkey' => '--ssl-key', + 'sslcert' => '--ssl-cert', + 'sslca' => '--ssl-ca', + 'sslcapath' => '--ssl-capath', + 'sslcipher' => '--ssl-cipher' } args.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact end def pg_env - ENV['PGUSER'] = config["username"] if config["username"] - ENV['PGHOST'] = config["host"] if config["host"] - ENV['PGPORT'] = config["port"].to_s if config["port"] - ENV['PGPASSWORD'] = config["password"].to_s if config["password"] + args = { + 'username' => 'PGUSER', + 'host' => 'PGHOST', + 'port' => 'PGPORT', + 'password' => 'PGPASSWORD', + # SSL + 'sslmode' => 'PGSSLMODE', + 'sslkey' => 'PGSSLKEY', + 'sslcert' => 'PGSSLCERT', + 'sslrootcert' => 'PGSSLROOTCERT', + 'sslcrl' => 'PGSSLCRL', + 'sslcompression' => 'PGSSLCOMPRESSION' + } + args.each { |opt, arg| ENV[arg] = config[opt].to_s if config[opt] } end def report_success(success) diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index eee5601b0ed..ea918b23a63 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -108,7 +108,7 @@ module Gitlab token = Doorkeeper::AccessToken.by_token(password) if valid_oauth_token?(token) user = User.find_by(id: token.resource_owner_id) - Gitlab::Auth::Result.new(user, nil, :oauth, read_authentication_abilities) + Gitlab::Auth::Result.new(user, nil, :oauth, full_authentication_abilities) end end end diff --git a/lib/gitlab/diff/position_tracer.rb b/lib/gitlab/diff/position_tracer.rb index 4d04f867268..c7542a8fabc 100644 --- a/lib/gitlab/diff/position_tracer.rb +++ b/lib/gitlab/diff/position_tracer.rb @@ -82,7 +82,7 @@ module Gitlab file_diff, old_line, new_line = results - Position.new( + new_position = Position.new( old_path: file_diff.old_path, new_path: file_diff.new_path, head_sha: new_diff_refs.head_sha, @@ -91,6 +91,13 @@ module Gitlab old_line: old_line, new_line: new_line ) + + # If a position is found, but is not actually contained in the diff, for example + # because it was an unchanged line in the context of a change that was undone, + # we cannot return this as a successful trace. + return unless new_position.diff_line(repository) + + new_position end private diff --git a/lib/gitlab/email/handler/base_handler.rb b/lib/gitlab/email/handler/base_handler.rb index 3f6ace0311a..0bba433d04b 100644 --- a/lib/gitlab/email/handler/base_handler.rb +++ b/lib/gitlab/email/handler/base_handler.rb @@ -16,6 +16,10 @@ module Gitlab def execute raise NotImplementedError end + + def metrics_params + { handler: self.class.name } + end end end end diff --git a/lib/gitlab/email/handler/create_issue_handler.rb b/lib/gitlab/email/handler/create_issue_handler.rb index b8ec9138c10..e7f91607e7e 100644 --- a/lib/gitlab/email/handler/create_issue_handler.rb +++ b/lib/gitlab/email/handler/create_issue_handler.rb @@ -1,4 +1,3 @@ - require 'gitlab/email/handler/base_handler' module Gitlab @@ -37,6 +36,10 @@ module Gitlab @project ||= Project.find_by_full_path(project_path) end + def metrics_params + super.merge(project: project) + end + private def create_issue diff --git a/lib/gitlab/email/handler/create_note_handler.rb b/lib/gitlab/email/handler/create_note_handler.rb index c66b0435f3a..31bb775c357 100644 --- a/lib/gitlab/email/handler/create_note_handler.rb +++ b/lib/gitlab/email/handler/create_note_handler.rb @@ -28,6 +28,10 @@ module Gitlab record_name: 'comment') end + def metrics_params + super.merge(project: project) + end + private def author diff --git a/lib/gitlab/email/handler/unsubscribe_handler.rb b/lib/gitlab/email/handler/unsubscribe_handler.rb index df491f060bf..df70a063330 100644 --- a/lib/gitlab/email/handler/unsubscribe_handler.rb +++ b/lib/gitlab/email/handler/unsubscribe_handler.rb @@ -19,6 +19,10 @@ module Gitlab noteable.unsubscribe(sent_notification.recipient) end + def metrics_params + super.merge(project: project) + end + private def sent_notification diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb index bb4fdd1f1f4..419d56a51e0 100644 --- a/lib/gitlab/email/receiver.rb +++ b/lib/gitlab/email/receiver.rb @@ -1,4 +1,3 @@ - require_dependency 'gitlab/email/handler' # Inspired in great part by Discourse's Email::Receiver @@ -32,9 +31,7 @@ module Gitlab raise UnknownIncomingEmail unless handler - Gitlab::Metrics.add_event(:receive_email, - project: handler.try(:project), - handler: handler.class.name) + Gitlab::Metrics.add_event(:receive_email, handler.metrics_params) handler.execute end diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index e6e40f6945d..c551f939df1 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -168,7 +168,7 @@ module Gitlab end def secret_path - Rails.root.join('.gitlab_workhorse_secret') + Gitlab.config.workhorse.secret_file end def set_key_and_notify(key, value, expire: nil, overwrite: true) diff --git a/package.json b/package.json index e65f30eea77..f8c151ebd81 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,10 @@ "js-cookie": "^2.1.3", "jszip": "^3.1.3", "jszip-utils": "^0.0.2", + "marked": "^0.3.6", "mousetrap": "^1.4.6", "pikaday": "^1.5.1", + "prismjs": "^1.6.0", "raphael": "^2.2.7", "raw-loader": "^0.5.1", "react-dev-utils": "^0.5.2", diff --git a/scripts/prepare_build.sh b/scripts/prepare_build.sh index 6cacb81b8bc..de7379425cf 100755 --- a/scripts/prepare_build.sh +++ b/scripts/prepare_build.sh @@ -1,26 +1,48 @@ #!/bin/sh -retry() { - if eval "$@"; then - return 0 - fi +. scripts/utils.sh + +export SETUP_DB=${SETUP_DB:-true} +export USE_BUNDLE_INSTALL=${USE_BUNDLE_INSTALL:-true} +export BUNDLE_INSTALL_FLAGS="--without production --jobs $(nproc) --path vendor --retry 3 --quiet" + +# Determine the database by looking at the job name. +# For example, we'll get pg if the job is `rspec pg 19 20` +export GITLAB_DATABASE=$(echo $CI_JOB_NAME | cut -f2 -d' ') + +# This would make the default database postgresql, and we could also use +# pg to mean postgresql. +if [ "$GITLAB_DATABASE" != 'mysql' ]; then + export GITLAB_DATABASE='postgresql' +fi + +cp config/database.yml.$GITLAB_DATABASE config/database.yml - for i in 2 1; do - sleep 3s - echo "Retrying $i..." - if eval "$@"; then - return 0 - fi - done - return 1 -} - -cp config/database.yml.mysql config/database.yml -sed -i 's/username:.*/username: root/g' config/database.yml -sed -i 's/password:.*/password:/g' config/database.yml -sed -i 's/# socket:.*/host: mysql/g' config/database.yml +if [ "$GITLAB_DATABASE" = 'postgresql' ]; then + sed -i 's/# host:.*/host: postgres/g' config/database.yml +else # Assume it's mysql + sed -i 's/username:.*/username: root/g' config/database.yml + sed -i 's/password:.*/password:/g' config/database.yml + sed -i 's/# host:.*/host: mysql/g' config/database.yml +fi cp config/resque.yml.example config/resque.yml sed -i 's/localhost/redis/g' config/resque.yml -export FLAGS="--path vendor --retry 3 --quiet" +cp config/gitlab.yml.example config/gitlab.yml + +if [ "$USE_BUNDLE_INSTALL" != "false" ]; then + retry bundle install --clean $BUNDLE_INSTALL_FLAGS +fi + +# Only install knapsack after bundle install! Otherwise oddly some native +# gems could not be found under some circumstance. No idea why, hours wasted. +retry gem install knapsack fog-aws mime-types + +if [ "$SETUP_DB" != "false" ]; then + bundle exec rake db:drop db:create db:schema:load db:migrate + + if [ "$GITLAB_DATABASE" = "mysql" ]; then + bundle exec rake add_limits_mysql + fi +fi diff --git a/scripts/utils.sh b/scripts/utils.sh new file mode 100644 index 00000000000..6faa701f0ce --- /dev/null +++ b/scripts/utils.sh @@ -0,0 +1,14 @@ +retry() { + if eval "$@"; then + return 0 + fi + + for i in 2 1; do + sleep 3s + echo "Retrying $i..." + if eval "$@"; then + return 0 + fi + done + return 1 +} diff --git a/spec/controllers/dashboard/todos_controller_spec.rb b/spec/controllers/dashboard/todos_controller_spec.rb index 6075259ea99..762e90f4a16 100644 --- a/spec/controllers/dashboard/todos_controller_spec.rb +++ b/spec/controllers/dashboard/todos_controller_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe Dashboard::TodosController do - include ApiHelpers - let(:user) { create(:user) } let(:author) { create(:user) } let(:project) { create(:empty_project) } diff --git a/spec/controllers/projects/builds_controller_spec.rb b/spec/controllers/projects/builds_controller_spec.rb index faf3770f5e9..fb4ccfa58c2 100644 --- a/spec/controllers/projects/builds_controller_spec.rb +++ b/spec/controllers/projects/builds_controller_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe Projects::BuildsController do - include ApiHelpers - let(:user) { create(:user) } let(:project) { create(:empty_project, :public) } @@ -63,4 +61,44 @@ describe Projects::BuildsController do expect(json_response['favicon']).to eq "/assets/ci_favicons/#{status.favicon}.ico" end end + + describe 'GET trace.json' do + let(:pipeline) { create(:ci_pipeline, project: project) } + let(:build) { create(:ci_build, pipeline: pipeline) } + let(:user) { create(:user) } + + context 'when user is logged in as developer' do + before do + project.add_developer(user) + sign_in(user) + get_trace + end + + it 'traces build log' do + expect(response).to have_http_status(:ok) + expect(json_response['id']).to eq build.id + expect(json_response['status']).to eq build.status + end + end + + context 'when user is logged in as non member' do + before do + sign_in(user) + get_trace + end + + it 'traces build log' do + expect(response).to have_http_status(:ok) + expect(json_response['id']).to eq build.id + expect(json_response['status']).to eq build.status + end + end + + def get_trace + get :trace, namespace_id: project.namespace, + project_id: project, + id: build.id, + format: :json + end + end end diff --git a/spec/controllers/projects/builds_controller_specs.rb b/spec/controllers/projects/builds_controller_specs.rb deleted file mode 100644 index d501f7b3155..00000000000 --- a/spec/controllers/projects/builds_controller_specs.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'spec_helper' - -describe Projects::BuildsController do - include ApiHelpers - - let(:project) { create(:empty_project, :public) } - - describe 'GET trace.json' do - let(:pipeline) { create(:ci_pipeline, project: project) } - let(:build) { create(:ci_build, pipeline: pipeline) } - let(:user) { create(:user) } - - context 'when user is logged in as developer' do - before do - project.add_developer(user) - sign_in(user) - get_trace - end - - it 'traces build log' do - expect(response).to have_http_status(:ok) - expect(json_response['id']).to eq build.id - expect(json_response['status']).to eq build.status - end - end - - context 'when user is logged in as non member' do - before do - sign_in(user) - get_trace - end - - it 'traces build log' do - expect(response).to have_http_status(:ok) - expect(json_response['id']).to eq build.id - expect(json_response['status']).to eq build.status - end - end - - def get_trace - get :trace, namespace_id: project.namespace, - project_id: project, - id: build.id, - format: :json - end - end -end diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index 5525fbd8130..5c478534ff3 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe Projects::EnvironmentsController do - include ApiHelpers - let(:user) { create(:user) } let(:project) { create(:empty_project) } diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index cc393bd24f2..a793da4162a 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe Projects::MergeRequestsController do - include ApiHelpers - let(:project) { create(:project) } let(:user) { create(:user) } let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb index 14207bf6b7a..47e61c3cea8 100644 --- a/spec/controllers/projects/milestones_controller_spec.rb +++ b/spec/controllers/projects/milestones_controller_spec.rb @@ -5,6 +5,7 @@ describe Projects::MilestonesController do let(:user) { create(:user) } let(:milestone) { create(:milestone, project: project) } let(:issue) { create(:issue, project: project, milestone: milestone) } + let!(:label) { create(:label, project: project, title: 'Issue Label', issues: [issue]) } let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, milestone: milestone) } before do @@ -13,6 +14,20 @@ describe Projects::MilestonesController do controller.instance_variable_set(:@project, project) end + describe "#show" do + render_views + + def view_milestone + get :show, namespace_id: project.namespace.id, project_id: project.id, id: milestone.iid + end + + it 'shows milestone page' do + view_milestone + + expect(response).to have_http_status(200) + end + end + describe "#destroy" do it "removes milestone" do expect(issue.milestone_id).to eq(milestone.id) diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index d9192177a06..b9bacc5a64a 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe Projects::PipelinesController do - include ApiHelpers - let(:user) { create(:user) } let(:project) { create(:empty_project, :public) } diff --git a/spec/controllers/projects/todo_controller_spec.rb b/spec/controllers/projects/todo_controller_spec.rb index 9a7beeff6fe..c5a4153d991 100644 --- a/spec/controllers/projects/todo_controller_spec.rb +++ b/spec/controllers/projects/todo_controller_spec.rb @@ -1,8 +1,6 @@ require('spec_helper') describe Projects::TodosController do - include ApiHelpers - let(:user) { create(:user) } let(:project) { create(:empty_project) } let(:issue) { create(:issue, project: project) } diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb index 6d6c9165c83..fa3d9ee25c0 100644 --- a/spec/features/admin/admin_labels_spec.rb +++ b/spec/features/admin/admin_labels_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' RSpec.describe 'admin issues labels' do - include WaitForAjax - let!(:bug_label) { Label.create(title: 'bug', template: true) } let!(:feature_label) { Label.create(title: 'feature', template: true) } diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index f6c3bc6a58d..c5b1ef1295c 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe "Admin::Users", feature: true do - include WaitForAjax - let!(:user) do create(:omniauth_user, provider: 'twitter', extern_uid: '123456') end diff --git a/spec/features/auto_deploy_spec.rb b/spec/features/auto_deploy_spec.rb index 6f36c74c911..67b0f006854 100644 --- a/spec/features/auto_deploy_spec.rb +++ b/spec/features/auto_deploy_spec.rb @@ -1,10 +1,8 @@ require 'spec_helper' describe 'Auto deploy' do - include WaitForAjax - let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } before do project.create_kubernetes_service( diff --git a/spec/features/boards/add_issues_modal_spec.rb b/spec/features/boards/add_issues_modal_spec.rb index 248c31115ad..505e0b5c355 100644 --- a/spec/features/boards/add_issues_modal_spec.rb +++ b/spec/features/boards/add_issues_modal_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' describe 'Issue Boards add issue modal', :feature, :js do - include WaitForAjax include WaitForVueResource let(:project) { create(:empty_project, :public) } diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index 30ad169e30e..a172ce1e8c0 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' describe 'Issue Boards', feature: true, js: true do - include WaitForAjax include WaitForVueResource include DragTo diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb index e6d7cf106d4..f04a1a89e96 100644 --- a/spec/features/boards/new_issue_spec.rb +++ b/spec/features/boards/new_issue_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' describe 'Issue Boards new issue', feature: true, js: true do - include WaitForAjax include WaitForVueResource let(:project) { create(:empty_project, :public) } diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb index 3332e07ec31..bafa4f05937 100644 --- a/spec/features/boards/sidebar_spec.rb +++ b/spec/features/boards/sidebar_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' describe 'Issue Boards', feature: true, js: true do - include WaitForAjax include WaitForVueResource let(:user) { create(:user) } diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb index 35d090c4b7f..496faf87a16 100644 --- a/spec/features/calendar_spec.rb +++ b/spec/features/calendar_spec.rb @@ -1,10 +1,8 @@ require 'spec_helper' feature 'Contributions Calendar', :feature, :js do - include WaitForAjax - let(:user) { create(:user) } - let(:contributed_project) { create(:project, :public) } + let(:contributed_project) { create(:empty_project, :public) } let(:issue_note) { create(:note, project: contributed_project) } # Ex/ Sunday Jan 1, 2016 diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 881f1fca4d1..e6c4ab24de5 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe 'Commits' do include CiStatusHelper - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } describe 'CI' do before do diff --git a/spec/features/copy_as_gfm_spec.rb b/spec/features/copy_as_gfm_spec.rb index 55df7e45f79..64a6c70061b 100644 --- a/spec/features/copy_as_gfm_spec.rb +++ b/spec/features/copy_as_gfm_spec.rb @@ -433,7 +433,7 @@ describe 'Copy as GFM', feature: true, js: true do end describe 'Copying code' do - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } context 'from a diff' do before do diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb index 0648c89a5c7..b93275c330b 100644 --- a/spec/features/cycle_analytics_spec.rb +++ b/spec/features/cycle_analytics_spec.rb @@ -1,11 +1,9 @@ require 'spec_helper' feature 'Cycle Analytics', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user) } let(:guest) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:issue) { create(:issue, project: project, created_at: 2.days.ago) } let(:milestone) { create(:milestone, project: project) } let(:mr) { create_merge_request_closing_issue(issue) } diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb index dc9d09fa396..0e9e3f78be2 100644 --- a/spec/features/dashboard/datetime_on_tooltips_spec.rb +++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'Tooltips on .timeago dates', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:project, name: 'test', namespace: user.namespace) } let(:created_date) { Date.yesterday.to_time } diff --git a/spec/features/dashboard/groups_list_spec.rb b/spec/features/dashboard/groups_list_spec.rb index ca04107d33a..52b4d82e856 100644 --- a/spec/features/dashboard/groups_list_spec.rb +++ b/spec/features/dashboard/groups_list_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe 'Dashboard Groups page', js: true, feature: true do - include WaitForAjax - let!(:user) { create :user } let!(:group) { create(:group) } let!(:nested_group) { create(:group, :nested) } diff --git a/spec/features/dashboard/project_member_activity_index_spec.rb b/spec/features/dashboard/project_member_activity_index_spec.rb index 49d93db58a9..16c214ae060 100644 --- a/spec/features/dashboard/project_member_activity_index_spec.rb +++ b/spec/features/dashboard/project_member_activity_index_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'Project member activity', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:empty_project, :public, name: 'x', namespace: user.namespace) } diff --git a/spec/features/dashboard_issues_spec.rb b/spec/features/dashboard_issues_spec.rb index 8c61cdebc4b..b6b87905231 100644 --- a/spec/features/dashboard_issues_spec.rb +++ b/spec/features/dashboard_issues_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe "Dashboard Issues filtering", feature: true, js: true do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:empty_project) } let(:milestone) { create(:milestone, project: project) } context 'filtering by milestone' do diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb index 8c64b050e19..76c77e0bc5f 100644 --- a/spec/features/expand_collapse_diffs_spec.rb +++ b/spec/features/expand_collapse_diffs_spec.rb @@ -1,10 +1,8 @@ require 'spec_helper' feature 'Expand and collapse diffs', js: true, feature: true do - include WaitForAjax - let(:branch) { 'expand-collapse-diffs' } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } before do login_as :admin diff --git a/spec/features/explore/groups_list_spec.rb b/spec/features/explore/groups_list_spec.rb index 9daaaa8e555..8e5421a984b 100644 --- a/spec/features/explore/groups_list_spec.rb +++ b/spec/features/explore/groups_list_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe 'Explore Groups page', js: true, feature: true do - include WaitForAjax - let!(:user) { create :user } let!(:group) { create(:group) } let!(:public_group) { create(:group, :public) } diff --git a/spec/features/gitlab_flavored_markdown_spec.rb b/spec/features/gitlab_flavored_markdown_spec.rb index 876f33dd03e..01b1aee4fd3 100644 --- a/spec/features/gitlab_flavored_markdown_spec.rb +++ b/spec/features/gitlab_flavored_markdown_spec.rb @@ -1,28 +1,28 @@ require 'spec_helper' describe "GitLab Flavored Markdown", feature: true do - let(:project) { create(:project) } + let(:project) { create(:empty_project) } let(:issue) { create(:issue, project: project) } - let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let(:fred) do - u = create(:user, name: "fred") - project.team << [u, :master] - u + create(:user, name: 'fred') do |user| + project.add_master(user) + end end before do - allow_any_instance_of(Commit).to receive(:title). - and_return("fix #{issue.to_reference}\n\nask #{fred.to_reference} for details") + login_as(:user) + project.add_developer(@user) end - let(:commit) { project.commit } + describe "for commits" do + let(:project) { create(:project, :repository) } + let(:commit) { project.commit } - before do - login_as :user - project.team << [@user, :developer] - end + before do + allow_any_instance_of(Commit).to receive(:title). + and_return("fix #{issue.to_reference}\n\nask #{fred.to_reference} for details") + end - describe "for commits" do it "renders title in commits#index" do visit namespace_project_commits_path(project.namespace, project, 'master', limit: 1) @@ -92,6 +92,8 @@ describe "GitLab Flavored Markdown", feature: true do end describe "for merge requests" do + let(:project) { create(:project, :repository) } + before do @merge_request = create(:merge_request, source_project: project, target_project: project, title: "fix #{issue.to_reference}") end diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb index f6409e00f22..4b22b07494d 100644 --- a/spec/features/global_search_spec.rb +++ b/spec/features/global_search_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' feature 'Global search', feature: true do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:empty_project, namespace: user.namespace) } before do project.team << [user, :master] diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb index 8e67ab028d7..71df3c949db 100644 --- a/spec/features/issues/award_emoji_spec.rb +++ b/spec/features/issues/award_emoji_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' describe 'Awards Emoji', feature: true do - include WaitForAjax include WaitForVueResource let!(:project) { create(:project, :public) } diff --git a/spec/features/issues/bulk_assignment_labels_spec.rb b/spec/features/issues/bulk_assignment_labels_spec.rb index 2f59630b4fb..1de50d6d77e 100644 --- a/spec/features/issues/bulk_assignment_labels_spec.rb +++ b/spec/features/issues/bulk_assignment_labels_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' feature 'Issues > Labels bulk assignment', feature: true do - include WaitForAjax - let(:user) { create(:user) } let!(:project) { create(:project) } let!(:issue1) { create(:issue, project: project, title: "Issue 1") } diff --git a/spec/features/issues/create_issue_for_single_discussion_in_merge_request.rb b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb index 88e2cc60d79..3a5a79e03f4 100644 --- a/spec/features/issues/create_issue_for_single_discussion_in_merge_request.rb +++ b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb @@ -4,7 +4,7 @@ feature 'Resolve an open discussion in a merge request by creating an issue', fe let(:user) { create(:user) } let(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: true) } let(:merge_request) { create(:merge_request, source_project: project) } - let!(:discussion) { Discussion.for_diff_notes([create(:diff_note_on_merge_request, noteable: merge_request, project: project)]).first } + let!(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion } describe 'As a user with access to the project' do before do @@ -74,8 +74,8 @@ feature 'Resolve an open discussion in a merge request by creating an issue', fe it 'Shows a notice to ask someone else to resolve the discussions' do expect(page).to have_content("The discussion at #{merge_request.to_reference}"\ - "(discussion #{discussion.first_note.id}) will stay unresolved."\ - "Ask someone with permission to resolve it.") + " (discussion #{discussion.first_note.id}) will stay unresolved."\ + " Ask someone with permission to resolve it.") end end end diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb index 3d1a9ed1722..0b573d7cef4 100644 --- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' describe 'Dropdown assignee', :feature, :js do include FilteredSearchHelpers - include WaitForAjax let!(:project) { create(:empty_project) } let!(:user) { create(:user, name: 'administrator', username: 'root') } diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb index 990e3b3e60c..0579d6c80ab 100644 --- a/spec/features/issues/filtered_search/dropdown_author_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' describe 'Dropdown author', js: true, feature: true do include FilteredSearchHelpers - include WaitForAjax let!(:project) { create(:empty_project) } let!(:user) { create(:user, name: 'administrator', username: 'root') } diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb index cae01f37b6b..b9a37cfcc22 100644 --- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' describe 'Dropdown hint', :js, :feature do include FilteredSearchHelpers - include WaitForAjax let!(:project) { create(:empty_project) } let!(:user) { create(:user) } diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb index 6f00066de4d..81ee0e2e4f6 100644 --- a/spec/features/issues/filtered_search/filter_issues_spec.rb +++ b/spec/features/issues/filtered_search/filter_issues_spec.rb @@ -3,7 +3,6 @@ require 'spec_helper' describe 'Filter issues', js: true, feature: true do include Devise::Test::IntegrationHelpers include FilteredSearchHelpers - include WaitForAjax let!(:group) { create(:group) } let!(:project) { create(:project, group: group) } diff --git a/spec/features/issues/filtered_search/recent_searches_spec.rb b/spec/features/issues/filtered_search/recent_searches_spec.rb index f506065a242..08fe3b4553b 100644 --- a/spec/features/issues/filtered_search/recent_searches_spec.rb +++ b/spec/features/issues/filtered_search/recent_searches_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe 'Recent searches', js: true, feature: true do include FilteredSearchHelpers - include WaitForAjax let!(:group) { create(:group) } let!(:project) { create(:project, group: group) } diff --git a/spec/features/issues/filtered_search/search_bar_spec.rb b/spec/features/issues/filtered_search/search_bar_spec.rb index 28137f11b92..3ea95aed0a6 100644 --- a/spec/features/issues/filtered_search/search_bar_spec.rb +++ b/spec/features/issues/filtered_search/search_bar_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' describe 'Search bar', js: true, feature: true do include FilteredSearchHelpers - include WaitForAjax let!(:project) { create(:empty_project) } let!(:user) { create(:user) } diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 7135565294b..b571f6bd861 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' feature 'GFM autocomplete', feature: true, js: true do - include WaitForAjax let(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') } let(:project) { create(:project) } let(:label) { create(:label, project: project, title: 'special+') } diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index 85585587fb1..baacd7edb86 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' feature 'Issue Sidebar', feature: true do - include WaitForAjax include MobileHelpers let(:project) { create(:project, :public) } diff --git a/spec/features/issues/update_issues_spec.rb b/spec/features/issues/update_issues_spec.rb index ae5da3877a8..7fa83c1fcf7 100644 --- a/spec/features/issues/update_issues_spec.rb +++ b/spec/features/issues/update_issues_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' feature 'Multiple issue updating from issues#index', feature: true do - include WaitForAjax - let!(:project) { create(:project) } let!(:issue) { create(:issue, project: project) } let!(:user) { create(:user)} diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index 0a9cd11ad6e..4cd6c1171ac 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' feature 'Issues > User uses slash commands', feature: true, js: true do include SlashCommandsHelpers - include WaitForAjax it_behaves_like 'issuable record that supports slash commands in its description and notes', :issue do let(:issuable) { create(:issue, project: project) } diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 55eca187f6c..81cc8513454 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -4,22 +4,14 @@ describe 'Issues', feature: true do include DropzoneHelper include IssueHelpers include SortingHelper - include WaitForAjax - let(:project) { create(:project, :public) } + let(:project) { create(:empty_project, :public) } before do login_as :user user2 = create(:user) project.team << [[@user, user2], :developer] - - project.repository.create_file( - @user, - '.gitlab/issue_templates/bug.md', - 'this is a test "bug" template', - message: 'added issue template', - branch_name: 'master') end describe 'Edit issue' do @@ -378,7 +370,7 @@ describe 'Issues', feature: true do end describe 'when I want to reset my incoming email token' do - let(:project1) { create(:project, namespace: @user.namespace) } + let(:project1) { create(:empty_project, namespace: @user.namespace) } let!(:issue) { create(:issue, project: project1) } before do @@ -610,7 +602,16 @@ describe 'Issues', feature: true do end context 'form filled by URL parameters' do + let(:project) { create(:project, :public, :repository) } + before do + project.repository.create_file( + @user, + '.gitlab/issue_templates/bug.md', + 'this is a test "bug" template', + message: 'added issue template', + branch_name: 'master') + visit new_namespace_project_issue_path(project.namespace, project, issuable_template: 'bug') end diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index 18508a44184..43977ad2fc5 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'Merge request conflict resolution', js: true, feature: true do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:project) } diff --git a/spec/features/merge_requests/deleted_source_branch_spec.rb b/spec/features/merge_requests/deleted_source_branch_spec.rb index 0952b17b63e..648678e2b1a 100644 --- a/spec/features/merge_requests/deleted_source_branch_spec.rb +++ b/spec/features/merge_requests/deleted_source_branch_spec.rb @@ -4,8 +4,6 @@ require 'spec_helper' # message to be shown by JavaScript when the source branch was deleted. # Please do not remove "js: true". describe 'Deleted source branch', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user) } let(:merge_request) { create(:merge_request) } diff --git a/spec/features/merge_requests/diff_notes_avatars_spec.rb b/spec/features/merge_requests/diff_notes_avatars_spec.rb index 218d95a88b8..b2e170513c4 100644 --- a/spec/features/merge_requests/diff_notes_avatars_spec.rb +++ b/spec/features/merge_requests/diff_notes_avatars_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'Diff note avatars', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:project, :public) } let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") } diff --git a/spec/features/merge_requests/filter_by_labels_spec.rb b/spec/features/merge_requests/filter_by_labels_spec.rb index 55f3c1863ff..32a9082b9b9 100644 --- a/spec/features/merge_requests/filter_by_labels_spec.rb +++ b/spec/features/merge_requests/filter_by_labels_spec.rb @@ -3,7 +3,6 @@ require 'rails_helper' feature 'Issue filtering by Labels', feature: true, js: true do include FilteredSearchHelpers include MergeRequestHelpers - include WaitForAjax let(:project) { create(:project, :public) } let!(:user) { create(:user) } diff --git a/spec/features/merge_requests/filter_merge_requests_spec.rb b/spec/features/merge_requests/filter_merge_requests_spec.rb index 70e3997e716..2da60e9f4ad 100644 --- a/spec/features/merge_requests/filter_merge_requests_spec.rb +++ b/spec/features/merge_requests/filter_merge_requests_spec.rb @@ -3,7 +3,6 @@ require 'rails_helper' describe 'Filter merge requests', feature: true do include FilteredSearchHelpers include MergeRequestHelpers - include WaitForAjax let!(:project) { create(:project) } let!(:group) { create(:group) } diff --git a/spec/features/merge_requests/mini_pipeline_graph_spec.rb b/spec/features/merge_requests/mini_pipeline_graph_spec.rb index 84ad8765d8f..449a60c1d05 100644 --- a/spec/features/merge_requests/mini_pipeline_graph_spec.rb +++ b/spec/features/merge_requests/mini_pipeline_graph_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' feature 'Mini Pipeline Graph', :js, :feature do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:project, :public) } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/features/merge_requests/pipelines_spec.rb b/spec/features/merge_requests/pipelines_spec.rb index 9c4c0525267..99e283ac181 100644 --- a/spec/features/merge_requests/pipelines_spec.rb +++ b/spec/features/merge_requests/pipelines_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'Pipelines for Merge Requests', feature: true, js: true do - include WaitForAjax - given(:user) { create(:user) } given(:merge_request) { create(:merge_request) } given(:project) { merge_request.target_project } diff --git a/spec/features/merge_requests/reset_filters_spec.rb b/spec/features/merge_requests/reset_filters_spec.rb index df5943f9136..275f81f50dc 100644 --- a/spec/features/merge_requests/reset_filters_spec.rb +++ b/spec/features/merge_requests/reset_filters_spec.rb @@ -3,7 +3,6 @@ require 'rails_helper' feature 'Merge requests filter clear button', feature: true, js: true do include FilteredSearchHelpers include MergeRequestHelpers - include WaitForAjax include IssueHelpers let!(:project) { create(:project, :public) } diff --git a/spec/features/merge_requests/update_merge_requests_spec.rb b/spec/features/merge_requests/update_merge_requests_spec.rb index b56fdfe5611..9ecc998785b 100644 --- a/spec/features/merge_requests/update_merge_requests_spec.rb +++ b/spec/features/merge_requests/update_merge_requests_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' feature 'Multiple merge requests updating from merge_requests#index', feature: true do - include WaitForAjax - let!(:user) { create(:user)} let!(:project) { create(:project) } let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) } diff --git a/spec/features/merge_requests/user_posts_notes.rb b/spec/features/merge_requests/user_posts_notes_spec.rb index c7cc4d6bc72..c7cc4d6bc72 100644 --- a/spec/features/merge_requests/user_posts_notes.rb +++ b/spec/features/merge_requests/user_posts_notes_spec.rb diff --git a/spec/features/merge_requests/user_uses_slash_commands_spec.rb b/spec/features/merge_requests/user_uses_slash_commands_spec.rb index a1f4eb2688b..1c0f21e5616 100644 --- a/spec/features/merge_requests/user_uses_slash_commands_spec.rb +++ b/spec/features/merge_requests/user_uses_slash_commands_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' feature 'Merge Requests > User uses slash commands', feature: true, js: true do include SlashCommandsHelpers - include WaitForAjax let(:user) { create(:user) } let(:project) { create(:project, :public) } diff --git a/spec/features/merge_requests/widget_deployments_spec.rb b/spec/features/merge_requests/widget_deployments_spec.rb index 6676821b807..00d191ddf2c 100644 --- a/spec/features/merge_requests/widget_deployments_spec.rb +++ b/spec/features/merge_requests/widget_deployments_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'Widget Deployments Header', feature: true, js: true do - include WaitForAjax - describe 'when deployed to an environment' do given(:user) { create(:user) } given(:project) { merge_request.target_project } diff --git a/spec/features/merge_requests/widget_spec.rb b/spec/features/merge_requests/widget_spec.rb index 4e128cd4a7d..d918181a238 100644 --- a/spec/features/merge_requests/widget_spec.rb +++ b/spec/features/merge_requests/widget_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' describe 'Merge request', :feature, :js do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:project) } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb index c3297de709a..c07de01c594 100644 --- a/spec/features/milestone_spec.rb +++ b/spec/features/milestone_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' feature 'Milestone', feature: true do - include WaitForAjax - let(:project) { create(:empty_project, :public) } let(:user) { create(:user) } diff --git a/spec/features/milestones/milestones_spec.rb b/spec/features/milestones/milestones_spec.rb index 2fa3e72ab08..50d7ca39045 100644 --- a/spec/features/milestones/milestones_spec.rb +++ b/spec/features/milestones/milestones_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' describe 'Milestone draggable', feature: true, js: true do - include WaitForAjax include DragTo let(:milestone) { create(:milestone, project: project, title: 8.14) } diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb index decad589c23..449ce80bc71 100644 --- a/spec/features/participants_autocomplete_spec.rb +++ b/spec/features/participants_autocomplete_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' feature 'Member autocomplete', :js do - let(:project) { create(:project, :public) } + let(:project) { create(:empty_project, :public) } let(:user) { create(:user) } let(:author) { create(:user) } let(:note) { create(:note, noteable: noteable, project: noteable.project) } @@ -36,6 +36,7 @@ feature 'Member autocomplete', :js do end context 'adding a new note on a Merge Request' do + let(:project) { create(:project, :public, :repository) } let(:noteable) do create(:merge_request, source_project: project, target_project: project, author: author) @@ -48,6 +49,7 @@ feature 'Member autocomplete', :js do end context 'adding a new note on a Commit' do + let(:project) { create(:project, :public, :repository) } let(:noteable) { project.commit } let(:note) { create(:note_on_commit, project: project, commit_id: project.commit.id) } diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 01cd268ffe8..7cfa5b9716f 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' feature 'File blob', feature: true do - include WaitForAjax include TreeHelper let(:project) { create(:project, :public, :test_repo) } diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb index aab5a72678e..cc5b1a7e734 100644 --- a/spec/features/projects/blobs/edit_spec.rb +++ b/spec/features/projects/blobs/edit_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' feature 'Editing file blob', feature: true, js: true do - include WaitForAjax include TreeHelper let(:project) { create(:project, :public, :test_repo) } diff --git a/spec/features/projects/blobs/user_create_spec.rb b/spec/features/projects/blobs/user_create_spec.rb index 6ea149956fe..d805450e095 100644 --- a/spec/features/projects/blobs/user_create_spec.rb +++ b/spec/features/projects/blobs/user_create_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' feature 'New blob creation', feature: true, js: true do - include WaitForAjax include TargetBranchHelpers given(:user) { create(:user) } diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb index 0b972d2a439..5d64d42fd61 100644 --- a/spec/features/projects/commit/cherry_pick_spec.rb +++ b/spec/features/projects/commit/cherry_pick_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -include WaitForAjax describe 'Cherry-pick Commits' do let(:group) { create(:group) } diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb index 30a2b2bcf8c..98c0f2c63b0 100644 --- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb +++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' feature 'Mini Pipeline Graph in Commit View', :js, :feature do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:project, :public) } diff --git a/spec/features/projects/edit_spec.rb b/spec/features/projects/edit_spec.rb index 7c319af893b..a263781c43c 100644 --- a/spec/features/projects/edit_spec.rb +++ b/spec/features/projects/edit_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' feature 'Project edit', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:project) } diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index 9079350186d..b080a8d500e 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -1,9 +1,6 @@ require 'spec_helper' -include WaitForAjax describe 'Edit Project Settings', feature: true do - include WaitForAjax - let(:member) { create(:user) } let!(:project) { create(:project, :public, path: 'gitlab', name: 'sample') } let!(:issue) { create(:issue, project: project) } diff --git a/spec/features/projects/files/creating_a_file_spec.rb b/spec/features/projects/files/creating_a_file_spec.rb index de6905f2b58..69744ac3948 100644 --- a/spec/features/projects/files/creating_a_file_spec.rb +++ b/spec/features/projects/files/creating_a_file_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'User wants to create a file', feature: true do - include WaitForAjax - let(:project) { create(:project) } let(:user) { create(:user) } diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb index 32f33a3ca97..a7cc98a2059 100644 --- a/spec/features/projects/files/dockerfile_dropdown_spec.rb +++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'User wants to add a Dockerfile file', feature: true do - include WaitForAjax - before do user = create(:user) project = create(:project) diff --git a/spec/features/projects/files/editing_a_file_spec.rb b/spec/features/projects/files/editing_a_file_spec.rb index 4da34108b46..7a3afafec29 100644 --- a/spec/features/projects/files/editing_a_file_spec.rb +++ b/spec/features/projects/files/editing_a_file_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'User wants to edit a file', feature: true do - include WaitForAjax - let(:project) { create(:project) } let(:user) { create(:user) } let(:commit_params) do diff --git a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb index 10b91d8990b..5c8105de4cb 100644 --- a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb +++ b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'User views files page', feature: true do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:forked_project_with_submodules) } diff --git a/spec/features/projects/files/find_file_keyboard_spec.rb b/spec/features/projects/files/find_file_keyboard_spec.rb index 582349d8d5b..e7a6749d8ac 100644 --- a/spec/features/projects/files/find_file_keyboard_spec.rb +++ b/spec/features/projects/files/find_file_keyboard_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'Find file keyboard shortcuts', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:project) } diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb index 9ebef505b92..e59428f8b24 100644 --- a/spec/features/projects/files/gitignore_dropdown_spec.rb +++ b/spec/features/projects/files/gitignore_dropdown_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'User wants to add a .gitignore file', feature: true do - include WaitForAjax - before do user = create(:user) project = create(:project) diff --git a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb index fca40f68b01..85b66b93fba 100644 --- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb +++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'User wants to add a .gitlab-ci.yml file', feature: true do - include WaitForAjax - before do user = create(:user) project = create(:project) diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb index 8ff0f5898ec..249830921ac 100644 --- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb +++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'project owner creates a license file', feature: true, js: true do - include WaitForAjax - let(:project_master) { create(:user) } let(:project) { create(:project) } background do diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb index 1a1910455a1..70a41886985 100644 --- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb +++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'project owner sees a link to create a license file in empty project', feature: true, js: true do - include WaitForAjax - let(:project_master) { create(:user) } let(:project) { create(:empty_project) } background do diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb index c51851d3f94..cd3af0b7d29 100644 --- a/spec/features/projects/files/undo_template_spec.rb +++ b/spec/features/projects/files/undo_template_spec.rb @@ -1,26 +1,25 @@ require 'spec_helper' -include WaitForAjax -feature 'Template Undo Button', js: true do +feature 'Template Undo Button', js: true do let(:project) { create(:project) } let(:user) { create(:user) } before do project.team << [user, :master] - login_as user + login_as user end - - context 'editing a matching file and applying a template' do + + context 'editing a matching file and applying a template' do before do - visit namespace_project_edit_blob_path(project.namespace, project, File.join(project.default_branch, "LICENSE")) + visit namespace_project_edit_blob_path(project.namespace, project, File.join(project.default_branch, "LICENSE")) select_file_template('.js-license-selector', 'Apache License 2.0') end - + scenario 'reverts template application' do try_template_undo('http://www.apache.org/licenses/', 'Apply a license template') end end - + context 'creating a non-matching file' do before do visit namespace_project_new_blob_path(project.namespace, project, 'master') diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb index 6cdca0f114b..d28a853bbc2 100644 --- a/spec/features/projects/issuable_templates_spec.rb +++ b/spec/features/projects/issuable_templates_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'issuable templates', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user) } let(:project) { create(:project, :public) } diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb index 1e900d7e660..836f81fb16d 100644 --- a/spec/features/projects/labels/update_prioritization_spec.rb +++ b/spec/features/projects/labels/update_prioritization_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' feature 'Prioritize labels', feature: true do - include WaitForAjax include DragTo let(:user) { create(:user) } diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index cffb935ad5a..ab2b089db2e 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'Projects > Members > Anonymous user sees members', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user) } let(:group) { create(:group, :public) } let(:project) { create(:empty_project, :public) } diff --git a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb index c3f45be6e4b..19d14ad9af4 100644 --- a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb +++ b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' feature 'Projects > Members > Master adds member with expiration date', feature: true, js: true do - include WaitForAjax include Select2Helper include ActiveSupport::Testing::TimeHelpers diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb index de25d45f447..1bf8f710b9f 100644 --- a/spec/features/projects/members/user_requests_access_spec.rb +++ b/spec/features/projects/members/user_requests_access_spec.rb @@ -31,6 +31,17 @@ feature 'Projects > Members > User requests access', feature: true do expect(page).not_to have_content 'Leave Project' end + context 'code access is restricted' do + scenario 'user can request access' do + project.project_feature.update!(repository_access_level: ProjectFeature::PRIVATE, + builds_access_level: ProjectFeature::PRIVATE, + merge_requests_access_level: ProjectFeature::PRIVATE) + visit namespace_project_path(project.namespace, project) + + expect(page).to have_content 'Request Access' + end + end + scenario 'user is not listed in the project members page' do click_link 'Request Access' diff --git a/spec/features/projects/ref_switcher_spec.rb b/spec/features/projects/ref_switcher_spec.rb index 3b8f0b2d3f8..881ad7910dd 100644 --- a/spec/features/projects/ref_switcher_spec.rb +++ b/spec/features/projects/ref_switcher_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' feature 'Ref switcher', feature: true, js: true do - include WaitForAjax let(:user) { create(:user) } let(:project) { create(:project, :public) } diff --git a/spec/features/projects/user_create_dir_spec.rb b/spec/features/projects/user_create_dir_spec.rb index 2065abfb248..5dfdc465d7d 100644 --- a/spec/features/projects/user_create_dir_spec.rb +++ b/spec/features/projects/user_create_dir_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' feature 'New directory creation', feature: true, js: true do - include WaitForAjax include TargetBranchHelpers given(:user) { create(:user) } diff --git a/spec/features/projects/view_on_env_spec.rb b/spec/features/projects/view_on_env_spec.rb index 34c6a10950f..b7a41ca54e6 100644 --- a/spec/features/projects/view_on_env_spec.rb +++ b/spec/features/projects/view_on_env_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe 'View on environment', js: true do - include WaitForAjax - let(:branch_name) { 'feature' } let(:file_path) { 'files/ruby/feature.rb' } let(:project) { create(:project, :repository) } diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index ba56030e28d..060e19596ae 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' feature 'Project', feature: true do describe 'description' do - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } let(:path) { namespace_project_path(project.namespace, project) } before do @@ -36,7 +36,7 @@ feature 'Project', feature: true do describe 'remove forked relationship', js: true do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:empty_project, namespace: user.namespace) } before do login_with user @@ -57,7 +57,7 @@ feature 'Project', feature: true do describe 'removal', js: true do let(:user) { create(:user, username: 'test', name: 'test') } - let(:project) { create(:project, namespace: user.namespace, name: 'project1') } + let(:project) { create(:empty_project, namespace: user.namespace, name: 'project1') } before do login_with(user) @@ -75,10 +75,8 @@ feature 'Project', feature: true do end describe 'project title' do - include WaitForAjax - let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:empty_project, namespace: user.namespace) } before do login_with(user) @@ -94,8 +92,8 @@ feature 'Project', feature: true do describe 'project title' do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } - let(:project2) { create(:project, namespace: user.namespace, path: 'test') } + let(:project) { create(:empty_project, namespace: user.namespace) } + let(:project2) { create(:empty_project, namespace: user.namespace, path: 'test') } let(:issue) { create(:issue, project: project) } context 'on issues page', js: true do diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb index 1a3f7b970f6..acc5641f930 100644 --- a/spec/features/protected_branches_spec.rb +++ b/spec/features/protected_branches_spec.rb @@ -2,10 +2,8 @@ require 'spec_helper' Dir["./spec/features/protected_branches/*.rb"].sort.each { |f| require f } feature 'Projected Branches', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user, :admin) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } before { login_as(user) } diff --git a/spec/features/protected_tags_spec.rb b/spec/features/protected_tags_spec.rb index 09e8c850de3..e3aa87ded28 100644 --- a/spec/features/protected_tags_spec.rb +++ b/spec/features/protected_tags_spec.rb @@ -2,10 +2,8 @@ require 'spec_helper' Dir["./spec/features/protected_tags/*.rb"].sort.each { |f| require f } feature 'Projected Tags', feature: true, js: true do - include WaitForAjax - let(:user) { create(:user, :admin) } - let(:project) { create(:project) } + let(:project) { create(:project, :repository) } before { login_as(user) } diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb index e8ad28a00f0..da6388dcdf2 100644 --- a/spec/features/search_spec.rb +++ b/spec/features/search_spec.rb @@ -2,10 +2,9 @@ require 'spec_helper' describe "Search", feature: true do include FilteredSearchHelpers - include WaitForAjax let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:empty_project, namespace: user.namespace) } let!(:issue) { create(:issue, project: project, assignee: user) } let!(:issue2) { create(:issue, project: project, author: user) } @@ -62,6 +61,7 @@ describe "Search", feature: true do context 'search for comments' do context 'when comment belongs to a invalid commit' do + let(:project) { create(:project, :repository) } let(:note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'Bug here') } before { note.update_attributes(commit_id: 12345678) } @@ -103,6 +103,7 @@ describe "Search", feature: true do end it 'finds a commit' do + project = create(:project, :repository) { |p| p.add_reporter(user) } visit namespace_project_path(project.namespace, project) page.within '.search' do @@ -116,6 +117,7 @@ describe "Search", feature: true do end it 'finds a code' do + project = create(:project, :repository) { |p| p.add_reporter(user) } visit namespace_project_path(project.namespace, project) page.within '.search' do @@ -222,6 +224,8 @@ describe "Search", feature: true do end describe 'search for commits' do + let(:project) { create(:project, :repository) } + before do visit search_path(project_id: project.id) end diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb index a5d14aa19f1..c33692fc4a9 100644 --- a/spec/features/task_lists_spec.rb +++ b/spec/features/task_lists_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' feature 'Task Lists', feature: true do include Warden::Test::Helpers - let(:project) { create(:project) } + let(:project) { create(:empty_project) } let(:user) { create(:user) } let(:user2) { create(:user) } @@ -240,6 +240,7 @@ feature 'Task Lists', feature: true do end describe 'multiple tasks' do + let(:project) { create(:project, :repository) } let!(:merge) { create(:merge_request, :simple, description: markdown, author: user, source_project: project) } it 'renders for description' do diff --git a/spec/features/todos/todos_filtering_spec.rb b/spec/features/todos/todos_filtering_spec.rb index e8f06916d53..cecb98641a6 100644 --- a/spec/features/todos/todos_filtering_spec.rb +++ b/spec/features/todos/todos_filtering_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe 'Dashboard > User filters todos', feature: true, js: true do - include WaitForAjax - let(:user_1) { create(:user, username: 'user_1', name: 'user_1') } let(:user_2) { create(:user, username: 'user_2', name: 'user_2') } diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb index c270511c903..50c207fb9cb 100644 --- a/spec/features/todos/todos_spec.rb +++ b/spec/features/todos/todos_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe 'Dashboard Todos', feature: true do - include WaitForAjax - let(:user) { create(:user) } let(:author) { create(:user) } let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } diff --git a/spec/features/u2f_spec.rb b/spec/features/u2f_spec.rb index c877cfdd978..544d2dcb87f 100644 --- a/spec/features/u2f_spec.rb +++ b/spec/features/u2f_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do - include WaitForAjax - before { allow_any_instance_of(U2fHelper).to receive(:inject_u2f_api?).and_return(true) } def manage_two_factor_authentication diff --git a/spec/features/users/projects_spec.rb b/spec/features/users/projects_spec.rb index 1d75fe434b0..373b64808f8 100644 --- a/spec/features/users/projects_spec.rb +++ b/spec/features/users/projects_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe 'Projects tab on a user profile', :feature, :js do - include WaitForAjax - let(:user) { create(:user) } let!(:project) { create(:empty_project, namespace: user.namespace) } let!(:project2) { create(:empty_project, namespace: user.namespace) } diff --git a/spec/features/users/snippets_spec.rb b/spec/features/users/snippets_spec.rb index ce7e809ec76..1546a06b80c 100644 --- a/spec/features/users/snippets_spec.rb +++ b/spec/features/users/snippets_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe 'Snippets tab on a user profile', feature: true, js: true do - include WaitForAjax - context 'when the user has snippets' do let(:user) { create(:user) } let!(:snippets) { create_list(:snippet, 2, :public, author: user) } diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 2de0fbe7ab2..c43feadc808 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -68,7 +68,6 @@ feature 'Users', feature: true, js: true do end feature 'username validation' do - include WaitForAjax let(:loading_icon) { '.fa.fa-spinner' } let(:username_input) { 'new_user_username' } diff --git a/spec/features/variables_spec.rb b/spec/features/variables_spec.rb index a362d6fd3b6..b83a230c1f8 100644 --- a/spec/features/variables_spec.rb +++ b/spec/features/variables_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe 'Project variables', js: true do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:empty_project) } let(:variable) { create(:ci_variable, key: 'test_key', value: 'test value') } before do diff --git a/spec/helpers/ci_status_helper_spec.rb b/spec/helpers/ci_status_helper_spec.rb index c795fe5a2a3..3dc13001056 100644 --- a/spec/helpers/ci_status_helper_spec.rb +++ b/spec/helpers/ci_status_helper_spec.rb @@ -6,25 +6,54 @@ describe CiStatusHelper do let(:success_commit) { double("Ci::Pipeline", status: 'success') } let(:failed_commit) { double("Ci::Pipeline", status: 'failed') } - describe 'ci_icon_for_status' do + describe '#ci_icon_for_status' do it 'renders to correct svg on success' do - expect(helper).to receive(:render).with('shared/icons/icon_status_success.svg', anything) + expect(helper).to receive(:render) + .with('shared/icons/icon_status_success.svg', anything) + helper.ci_icon_for_status(success_commit.status) end + it 'renders the correct svg on failure' do - expect(helper).to receive(:render).with('shared/icons/icon_status_failed.svg', anything) + expect(helper).to receive(:render) + .with('shared/icons/icon_status_failed.svg', anything) + helper.ci_icon_for_status(failed_commit.status) end end + describe '#ci_text_for_status' do + context 'when status is manual' do + it 'changes the status to blocked' do + expect(helper.ci_text_for_status('manual')) + .to eq 'blocked' + end + end + + context 'when status is success' do + it 'changes the status to passed' do + expect(helper.ci_text_for_status('success')) + .to eq 'passed' + end + end + + context 'when status is something else' do + it 'returns status unchanged' do + expect(helper.ci_text_for_status('some-status')) + .to eq 'some-status' + end + end + end + describe "#pipeline_status_cache_key" do + let(:pipeline_status) do + Gitlab::Cache::Ci::ProjectPipelineStatus + .new(build(:project), sha: '123abc', status: 'success') + end + it "builds a cache key for pipeline status" do - pipeline_status = Gitlab::Cache::Ci::ProjectPipelineStatus.new( - build(:project), - sha: "123abc", - status: "success" - ) - expect(helper.pipeline_status_cache_key(pipeline_status)).to eq("pipeline-status/123abc-success") + expect(helper.pipeline_status_cache_key(pipeline_status)) + .to eq("pipeline-status/123abc-success") end end end diff --git a/spec/javascripts/fixtures/raw.rb b/spec/javascripts/fixtures/raw.rb new file mode 100644 index 00000000000..1ce622fc836 --- /dev/null +++ b/spec/javascripts/fixtures/raw.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe 'Raw files', '(JavaScript fixtures)', type: :controller do + include JavaScriptFixturesHelpers + + let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} + let(:project) { create(:project, namespace: namespace, path: 'raw-project') } + + before(:all) do + clean_frontend_fixtures('blob/notebook/') + end + + it 'blob/notebook/basic.json' do |example| + blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb') + + store_frontend_fixture(blob.data, example.description) + end + + it 'blob/notebook/worksheets.json' do |example| + blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb') + + store_frontend_fixture(blob.data, example.description) + end +end diff --git a/spec/javascripts/notebook/cells/code_spec.js b/spec/javascripts/notebook/cells/code_spec.js new file mode 100644 index 00000000000..0c432d73f67 --- /dev/null +++ b/spec/javascripts/notebook/cells/code_spec.js @@ -0,0 +1,55 @@ +import Vue from 'vue'; +import CodeComponent from '~/notebook/cells/code.vue'; + +const Component = Vue.extend(CodeComponent); + +describe('Code component', () => { + let vm; + let json; + + beforeEach(() => { + json = getJSONFixture('blob/notebook/basic.json'); + }); + + describe('without output', () => { + beforeEach((done) => { + vm = new Component({ + propsData: { + cell: json.cells[0], + }, + }); + vm.$mount(); + + setTimeout(() => { + done(); + }); + }); + + it('does not render output prompt', () => { + expect(vm.$el.querySelectorAll('.prompt').length).toBe(1); + }); + }); + + describe('with output', () => { + beforeEach((done) => { + vm = new Component({ + propsData: { + cell: json.cells[2], + }, + }); + vm.$mount(); + + setTimeout(() => { + done(); + }); + }); + + it('does not render output prompt', () => { + expect(vm.$el.querySelectorAll('.prompt').length).toBe(2); + }); + + it('renders output cell', () => { + expect(vm.$el.querySelector('.output')).toBeDefined(); + }); + }); +}); diff --git a/spec/javascripts/notebook/cells/markdown_spec.js b/spec/javascripts/notebook/cells/markdown_spec.js new file mode 100644 index 00000000000..38c976f38d8 --- /dev/null +++ b/spec/javascripts/notebook/cells/markdown_spec.js @@ -0,0 +1,41 @@ +import Vue from 'vue'; +import MarkdownComponent from '~/notebook/cells/markdown.vue'; + +const Component = Vue.extend(MarkdownComponent); + +describe('Markdown component', () => { + let vm; + let cell; + let json; + + beforeEach((done) => { + json = getJSONFixture('blob/notebook/basic.json'); + + cell = json.cells[1]; + + vm = new Component({ + propsData: { + cell, + }, + }); + vm.$mount(); + + setTimeout(() => { + done(); + }); + }); + + it('does not render promot', () => { + expect(vm.$el.querySelector('.prompt span')).toBeNull(); + }); + + it('does not render the markdown text', () => { + expect( + vm.$el.querySelector('.markdown').innerHTML.trim(), + ).not.toEqual(cell.source.join('')); + }); + + it('renders the markdown HTML', () => { + expect(vm.$el.querySelector('.markdown h1')).not.toBeNull(); + }); +}); diff --git a/spec/javascripts/notebook/cells/output/index_spec.js b/spec/javascripts/notebook/cells/output/index_spec.js new file mode 100644 index 00000000000..dbf79f85c7c --- /dev/null +++ b/spec/javascripts/notebook/cells/output/index_spec.js @@ -0,0 +1,126 @@ +import Vue from 'vue'; +import CodeComponent from '~/notebook/cells/output/index.vue'; + +const Component = Vue.extend(CodeComponent); + +describe('Output component', () => { + let vm; + let json; + + const createComponent = (output) => { + vm = new Component({ + propsData: { + output, + count: 1, + }, + }); + vm.$mount(); + }; + + beforeEach(() => { + json = getJSONFixture('blob/notebook/basic.json'); + }); + + describe('text output', () => { + beforeEach((done) => { + createComponent(json.cells[2].outputs[0]); + + setTimeout(() => { + done(); + }); + }); + + it('renders as plain text', () => { + expect(vm.$el.querySelector('pre')).not.toBeNull(); + }); + + it('renders promot', () => { + expect(vm.$el.querySelector('.prompt span')).not.toBeNull(); + }); + }); + + describe('image output', () => { + beforeEach((done) => { + createComponent(json.cells[3].outputs[0]); + + setTimeout(() => { + done(); + }); + }); + + it('renders as an image', () => { + expect(vm.$el.querySelector('img')).not.toBeNull(); + }); + + it('does not render the prompt', () => { + expect(vm.$el.querySelector('.prompt span')).toBeNull(); + }); + }); + + describe('html output', () => { + beforeEach((done) => { + createComponent(json.cells[4].outputs[0]); + + setTimeout(() => { + done(); + }); + }); + + it('renders raw HTML', () => { + expect(vm.$el.querySelector('p')).not.toBeNull(); + expect(vm.$el.textContent.trim()).toBe('test'); + }); + + it('does not render the prompt', () => { + expect(vm.$el.querySelector('.prompt span')).toBeNull(); + }); + }); + + describe('svg output', () => { + beforeEach((done) => { + createComponent(json.cells[5].outputs[0]); + + setTimeout(() => { + done(); + }); + }); + + it('renders as an svg', () => { + expect(vm.$el.querySelector('svg')).not.toBeNull(); + }); + + it('does not render the prompt', () => { + expect(vm.$el.querySelector('.prompt span')).toBeNull(); + }); + }); + + describe('default to plain text', () => { + beforeEach((done) => { + createComponent(json.cells[6].outputs[0]); + + setTimeout(() => { + done(); + }); + }); + + it('renders as plain text', () => { + expect(vm.$el.querySelector('pre')).not.toBeNull(); + expect(vm.$el.textContent.trim()).toContain('testing'); + }); + + it('renders promot', () => { + expect(vm.$el.querySelector('.prompt span')).not.toBeNull(); + }); + + it('renders as plain text when doesn\'t recognise other types', (done) => { + createComponent(json.cells[7].outputs[0]); + + setTimeout(() => { + expect(vm.$el.querySelector('pre')).not.toBeNull(); + expect(vm.$el.textContent.trim()).toContain('testing'); + + done(); + }); + }); + }); +}); diff --git a/spec/javascripts/notebook/cells/prompt_spec.js b/spec/javascripts/notebook/cells/prompt_spec.js new file mode 100644 index 00000000000..207fa433a59 --- /dev/null +++ b/spec/javascripts/notebook/cells/prompt_spec.js @@ -0,0 +1,56 @@ +import Vue from 'vue'; +import PromptComponent from '~/notebook/cells/prompt.vue'; + +const Component = Vue.extend(PromptComponent); + +describe('Prompt component', () => { + let vm; + + describe('input', () => { + beforeEach((done) => { + vm = new Component({ + propsData: { + type: 'In', + count: 1, + }, + }); + vm.$mount(); + + setTimeout(() => { + done(); + }); + }); + + it('renders in label', () => { + expect(vm.$el.textContent.trim()).toContain('In'); + }); + + it('renders count', () => { + expect(vm.$el.textContent.trim()).toContain('1'); + }); + }); + + describe('output', () => { + beforeEach((done) => { + vm = new Component({ + propsData: { + type: 'Out', + count: 1, + }, + }); + vm.$mount(); + + setTimeout(() => { + done(); + }); + }); + + it('renders in label', () => { + expect(vm.$el.textContent.trim()).toContain('Out'); + }); + + it('renders count', () => { + expect(vm.$el.textContent.trim()).toContain('1'); + }); + }); +}); diff --git a/spec/javascripts/notebook/index_spec.js b/spec/javascripts/notebook/index_spec.js new file mode 100644 index 00000000000..bd63ab35426 --- /dev/null +++ b/spec/javascripts/notebook/index_spec.js @@ -0,0 +1,98 @@ +import Vue from 'vue'; +import Notebook from '~/notebook/index.vue'; + +const Component = Vue.extend(Notebook); + +describe('Notebook component', () => { + let vm; + let json; + let jsonWithWorksheet; + + beforeEach(() => { + json = getJSONFixture('blob/notebook/basic.json'); + jsonWithWorksheet = getJSONFixture('blob/notebook/worksheets.json'); + }); + + describe('without JSON', () => { + beforeEach((done) => { + vm = new Component({ + propsData: { + notebook: {}, + }, + }); + vm.$mount(); + + setTimeout(() => { + done(); + }); + }); + + it('does not render', () => { + expect(vm.$el.tagName).toBeUndefined(); + }); + }); + + describe('with JSON', () => { + beforeEach((done) => { + vm = new Component({ + propsData: { + notebook: json, + codeCssClass: 'js-code-class', + }, + }); + vm.$mount(); + + setTimeout(() => { + done(); + }); + }); + + it('renders cells', () => { + expect(vm.$el.querySelectorAll('.cell').length).toBe(json.cells.length); + }); + + it('renders markdown cell', () => { + expect(vm.$el.querySelector('.markdown')).not.toBeNull(); + }); + + it('renders code cell', () => { + expect(vm.$el.querySelector('pre')).not.toBeNull(); + }); + + it('add code class to code blocks', () => { + expect(vm.$el.querySelector('.js-code-class')).not.toBeNull(); + }); + }); + + describe('with worksheets', () => { + beforeEach((done) => { + vm = new Component({ + propsData: { + notebook: jsonWithWorksheet, + codeCssClass: 'js-code-class', + }, + }); + vm.$mount(); + + setTimeout(() => { + done(); + }); + }); + + it('renders cells', () => { + expect(vm.$el.querySelectorAll('.cell').length).toBe(jsonWithWorksheet.worksheets[0].cells.length); + }); + + it('renders markdown cell', () => { + expect(vm.$el.querySelector('.markdown')).not.toBeNull(); + }); + + it('renders code cell', () => { + expect(vm.$el.querySelector('pre')).not.toBeNull(); + }); + + it('add code class to code blocks', () => { + expect(vm.$el.querySelector('.js-code-class')).not.toBeNull(); + }); + }); +}); diff --git a/spec/javascripts/notebook/lib/highlight_spec.js b/spec/javascripts/notebook/lib/highlight_spec.js new file mode 100644 index 00000000000..d71c5718858 --- /dev/null +++ b/spec/javascripts/notebook/lib/highlight_spec.js @@ -0,0 +1,15 @@ +import Prism from '~/notebook/lib/highlight'; + +describe('Highlight library', () => { + it('imports python language', () => { + expect(Prism.languages.python).toBeDefined(); + }); + + it('uses custom CSS classes', () => { + const el = document.createElement('div'); + el.innerHTML = Prism.highlight('console.log("a");', Prism.languages.javascript); + + expect(el.querySelector('.s')).not.toBeNull(); + expect(el.querySelector('.nf')).not.toBeNull(); + }); +}); diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 03c4879ed6f..d4a43192d03 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -118,7 +118,7 @@ describe Gitlab::Auth, lib: true do it 'succeeds for OAuth tokens with the `api` scope' do expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: 'oauth2') - expect(gl_auth.find_for_git_client("oauth2", token_w_api_scope.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :oauth, read_authentication_abilities)) + expect(gl_auth.find_for_git_client("oauth2", token_w_api_scope.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :oauth, full_authentication_abilities)) end it 'fails for OAuth tokens with other scopes' do diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb index c166f83664a..a10a251dc4a 100644 --- a/spec/lib/gitlab/diff/position_tracer_spec.rb +++ b/spec/lib/gitlab/diff/position_tracer_spec.rb @@ -569,13 +569,8 @@ describe Gitlab::Diff::PositionTracer, lib: true do # 1 1 BB # 2 2 A - it "returns the new position" do - expect_new_position( - old_path: file_name, - new_path: new_file_name, - old_line: old_position.new_line, - new_line: old_position.new_line - ) + it "returns nil since the line doesn't exist in the new diffs anymore" do + expect(subject).to be_nil end end diff --git a/spec/lib/gitlab/other_markup.rb b/spec/lib/gitlab/other_markup_spec.rb index 8f5a353b381..22e80ec46be 100644 --- a/spec/lib/gitlab/other_markup.rb +++ b/spec/lib/gitlab/other_markup_spec.rb @@ -1,12 +1,14 @@ require 'spec_helper' describe Gitlab::OtherMarkup, lib: true do + let(:context) { {} } + context "XSS Checks" do links = { 'links' => { file: 'file.rdoc', input: 'XSS[JaVaScriPt:alert(1)]', - output: '<p><a>XSS</a></p>' + output: "\n" + '<p><a>XSS</a></p>' + "\n" } } links.each do |name, data| diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index d7d6a75d38d..3b222ea1c3d 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -296,32 +296,56 @@ describe Ci::Pipeline, models: true do describe 'state machine' do let(:current) { Time.now.change(usec: 0) } - let(:build) { create_build('build1', 0) } - let(:build_b) { create_build('build2', 0) } - let(:build_c) { create_build('build3', 0) } + let(:build) { create_build('build1', queued_at: 0) } + let(:build_b) { create_build('build2', queued_at: 0) } + let(:build_c) { create_build('build3', queued_at: 0) } describe '#duration' do - before do - travel_to(current + 30) do - build.run! - build.success! - build_b.run! - build_c.run! - end + context 'when multiple builds are finished' do + before do + travel_to(current + 30) do + build.run! + build.success! + build_b.run! + build_c.run! + end - travel_to(current + 40) do - build_b.drop! + travel_to(current + 40) do + build_b.drop! + end + + travel_to(current + 70) do + build_c.success! + end end - travel_to(current + 70) do - build_c.success! + it 'matches sum of builds duration' do + pipeline.reload + + expect(pipeline.duration).to eq(40) end end - it 'matches sum of builds duration' do - pipeline.reload + context 'when pipeline becomes blocked' do + let!(:build) { create_build('build:1') } + let!(:action) { create_build('manual:action', :manual) } + + before do + travel_to(current + 1.minute) do + build.run! + end + + travel_to(current + 5.minutes) do + build.success! + end + end + + it 'recalculates pipeline duration' do + pipeline.reload - expect(pipeline.duration).to eq(40) + expect(pipeline).to be_manual + expect(pipeline.duration).to eq 4.minutes + end end end @@ -376,19 +400,20 @@ describe Ci::Pipeline, models: true do end describe 'pipeline caching' do - it 'executes ExpirePipelinesCacheService' do - expect_any_instance_of(Ci::ExpirePipelineCacheService).to receive(:execute).with(pipeline) + it 'performs ExpirePipelinesCacheWorker' do + expect(ExpirePipelineCacheWorker).to receive(:perform_async).with(pipeline.id) pipeline.cancel end end - def create_build(name, queued_at = current, started_from = 0) - create(:ci_build, + def create_build(name, *traits, queued_at: current, started_from: 0, **opts) + create(:ci_build, *traits, name: name, pipeline: pipeline, queued_at: queued_at, - started_at: queued_at + started_from) + started_at: queued_at + started_from, + **opts) end end @@ -1014,11 +1039,12 @@ describe Ci::Pipeline, models: true do end describe "#merge_requests" do - let(:project) { create(:project, :repository) } - let(:pipeline) { FactoryGirl.create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: project.repository.commit('master').id) } + let(:project) { create(:empty_project) } + let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: 'a288a022a53a5a944fae87bcec6efc87b7061808') } it "returns merge requests whose `diff_head_sha` matches the pipeline's SHA" do merge_request = create(:merge_request, source_project: project, source_branch: pipeline.ref) + allow_any_instance_of(MergeRequest).to receive(:diff_head_sha) { 'a288a022a53a5a944fae87bcec6efc87b7061808' } expect(pipeline.merge_requests).to eq([merge_request]) end @@ -1037,6 +1063,23 @@ describe Ci::Pipeline, models: true do end end + describe "#all_merge_requests" do + let(:project) { create(:empty_project) } + let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master') } + + it "returns all merge requests having the same source branch" do + merge_request = create(:merge_request, source_project: project, source_branch: pipeline.ref) + + expect(pipeline.all_merge_requests).to eq([merge_request]) + end + + it "doesn't return merge requests having a different source branch" do + create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') + + expect(pipeline.all_merge_requests).to be_empty + end + end + describe '#stuck?' do before do create(:ci_build, :pending, pipeline: pipeline) diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb index f191605dbdb..221647d7a48 100644 --- a/spec/models/concerns/routable_spec.rb +++ b/spec/models/concerns/routable_spec.rb @@ -194,6 +194,24 @@ describe Group, 'Routable' do it { expect(group.full_path).to eq(group.path) } it { expect(nested_group.full_path).to eq("#{group.full_path}/#{nested_group.path}") } + + context 'with RequestStore active' do + before do + RequestStore.begin! + end + + after do + RequestStore.end! + RequestStore.clear! + end + + it 'does not load the route table more than once' do + expect(group).to receive(:uncached_full_path).once.and_call_original + + 3.times { group.full_path } + expect(group.full_path).to eq(group.path) + end + end end describe '#full_name' do diff --git a/spec/requests/api/access_requests_spec.rb b/spec/requests/api/access_requests_spec.rb index 46edbd49b28..c8eacb38e6f 100644 --- a/spec/requests/api/access_requests_spec.rb +++ b/spec/requests/api/access_requests_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::AccessRequests, api: true do - include ApiHelpers - +describe API::AccessRequests do let(:master) { create(:user) } let(:developer) { create(:user) } let(:access_requester) { create(:user) } diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb index f4d4a8a2cc7..bbdef0aeb1b 100644 --- a/spec/requests/api/award_emoji_spec.rb +++ b/spec/requests/api/award_emoji_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::AwardEmoji, api: true do - include ApiHelpers +describe API::AwardEmoji do let(:user) { create(:user) } let!(:project) { create(:empty_project) } let(:issue) { create(:issue, project: project) } diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb index 87c36639cd4..c27db716ef8 100644 --- a/spec/requests/api/boards_spec.rb +++ b/spec/requests/api/boards_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Boards, api: true do - include ApiHelpers - +describe API::Boards do let(:user) { create(:user) } let(:user2) { create(:user) } let(:non_member) { create(:user) } diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index a70f7beaae0..7eaa89837c8 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -1,9 +1,7 @@ require 'spec_helper' require 'mime/types' -describe API::Branches, api: true do - include ApiHelpers - +describe API::Branches do let(:user) { create(:user) } let!(:project) { create(:project, :repository, creator: user) } let!(:master) { create(:project_member, :master, user: user, project: project) } diff --git a/spec/requests/api/broadcast_messages_spec.rb b/spec/requests/api/broadcast_messages_spec.rb index 024fa66848c..67989689799 100644 --- a/spec/requests/api/broadcast_messages_spec.rb +++ b/spec/requests/api/broadcast_messages_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::BroadcastMessages, api: true do - include ApiHelpers - +describe API::BroadcastMessages do let(:user) { create(:user) } let(:admin) { create(:admin) } diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb index d8b3cc041a5..1233cdc64c4 100644 --- a/spec/requests/api/commit_statuses_spec.rb +++ b/spec/requests/api/commit_statuses_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::CommitStatuses, api: true do - include ApiHelpers - +describe API::CommitStatuses do let!(:project) { create(:project, :repository) } let(:commit) { project.repository.commit } let(:guest) { create_user(:guest) } diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 42dbab586cd..0b0e4c2b112 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -1,8 +1,7 @@ require 'spec_helper' require 'mime/types' -describe API::Commits, api: true do - include ApiHelpers +describe API::Commits do let(:user) { create(:user) } let(:user2) { create(:user) } let!(:project) { create(:project, :repository, creator: user, namespace: user.namespace) } diff --git a/spec/requests/api/deploy_keys_spec.rb b/spec/requests/api/deploy_keys_spec.rb index e1beac28dab..843e9862b0c 100644 --- a/spec/requests/api/deploy_keys_spec.rb +++ b/spec/requests/api/deploy_keys_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::DeployKeys, api: true do - include ApiHelpers - +describe API::DeployKeys do let(:user) { create(:user) } let(:admin) { create(:admin) } let(:project) { create(:empty_project, creator_id: user.id) } diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb index e55575ffbda..90d78d060ca 100644 --- a/spec/requests/api/deployments_spec.rb +++ b/spec/requests/api/deployments_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Deployments, api: true do - include ApiHelpers - +describe API::Deployments do let(:user) { create(:user) } let(:non_member) { create(:user) } let(:project) { deployment.environment.project } diff --git a/spec/requests/api/doorkeeper_access_spec.rb b/spec/requests/api/doorkeeper_access_spec.rb index f6fd567eca5..b5897b2e346 100644 --- a/spec/requests/api/doorkeeper_access_spec.rb +++ b/spec/requests/api/doorkeeper_access_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::API, api: true do - include ApiHelpers - +describe API::API do let!(:user) { create(:user) } let!(:application) { Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) } let!(:token) { Doorkeeper::AccessToken.create! application_id: application.id, resource_owner_id: user.id, scopes: "api" } diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb index b54ee8e8b85..aae03c84e1f 100644 --- a/spec/requests/api/environments_spec.rb +++ b/spec/requests/api/environments_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Environments, api: true do - include ApiHelpers - +describe API::Environments do let(:user) { create(:user) } let(:non_member) { create(:user) } let(:project) { create(:empty_project, :private, namespace: user.namespace) } diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index 6db2faed76b..fa28047d49c 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::Files, api: true do - include ApiHelpers +describe API::Files do let(:user) { create(:user) } let!(:project) { create(:project, :repository, namespace: user.namespace ) } let(:guest) { create(:user) { |u| project.add_guest(u) } } diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 2545da7b1db..3e27a3bee77 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::Groups, api: true do - include ApiHelpers +describe API::Groups do include UploadHelpers let(:user1) { create(:user, can_create_group: false) } diff --git a/spec/requests/api/helpers_spec.rb b/spec/requests/api/helpers_spec.rb index 988a57a80ea..4845ab1ae1f 100644 --- a/spec/requests/api/helpers_spec.rb +++ b/spec/requests/api/helpers_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe API::Helpers, api: true do +describe API::Helpers do include API::APIGuard::HelperMethods include API::Helpers include SentryHelper diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 3d6010ede73..429f1a4e375 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::Internal, api: true do - include ApiHelpers +describe API::Internal do let(:user) { create(:user) } let(:key) { create(:key, user: user) } let(:project) { create(:project, :repository) } diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 551aae7d701..b37be1e0c50 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::Issues, api: true do - include ApiHelpers +describe API::Issues do include EmailHelpers let(:user) { create(:user) } diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb index d8a56c02a63..decb5b91941 100644 --- a/spec/requests/api/jobs_spec.rb +++ b/spec/requests/api/jobs_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Jobs, api: true do - include ApiHelpers - +describe API::Jobs do let(:user) { create(:user) } let(:api_user) { user } let!(:project) { create(:project, :repository, creator: user, public_builds: false) } diff --git a/spec/requests/api/keys_spec.rb b/spec/requests/api/keys_spec.rb index 4c80987d680..b5586088485 100644 --- a/spec/requests/api/keys_spec.rb +++ b/spec/requests/api/keys_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Keys, api: true do - include ApiHelpers - +describe API::Keys do let(:user) { create(:user) } let(:admin) { create(:admin) } let(:key) { create(:key, user: user) } diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index a1adaba7b98..0c6b55c1630 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Labels, api: true do - include ApiHelpers - +describe API::Labels do let(:user) { create(:user) } let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } let!(:label1) { create(:label, title: 'label1', project: project) } diff --git a/spec/requests/api/lint_spec.rb b/spec/requests/api/lint_spec.rb index 391fc13a380..df7c91b5bc1 100644 --- a/spec/requests/api/lint_spec.rb +++ b/spec/requests/api/lint_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Lint, api: true do - include ApiHelpers - +describe API::Lint do describe 'POST /ci/lint' do context 'with valid .gitlab-ci.yaml content' do let(:yaml_content) do diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb index 84dca51801f..e095053fa03 100644 --- a/spec/requests/api/members_spec.rb +++ b/spec/requests/api/members_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Members, api: true do - include ApiHelpers - +describe API::Members do let(:master) { create(:user, username: 'master_user') } let(:developer) { create(:user) } let(:access_requester) { create(:user) } diff --git a/spec/requests/api/merge_request_diffs_spec.rb b/spec/requests/api/merge_request_diffs_spec.rb index 79f3151ba52..d1b22179888 100644 --- a/spec/requests/api/merge_request_diffs_spec.rb +++ b/spec/requests/api/merge_request_diffs_spec.rb @@ -1,8 +1,6 @@ require "spec_helper" -describe API::MergeRequestDiffs, 'MergeRequestDiffs', api: true do - include ApiHelpers - +describe API::MergeRequestDiffs, 'MergeRequestDiffs' do let!(:user) { create(:user) } let!(:merge_request) { create(:merge_request, importing: true) } let!(:project) { merge_request.target_project } diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 61d965e8974..91b1e1aee4d 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -1,12 +1,11 @@ require "spec_helper" -describe API::MergeRequests, api: true do - include ApiHelpers +describe API::MergeRequests do let(:base_time) { Time.now } let(:user) { create(:user) } let(:admin) { create(:user, :admin) } let(:non_member) { create(:user) } - let!(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace) } + let!(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) } let!(:merge_request) { create(:merge_request, :simple, author: user, assignee: user, source_project: project, title: "Test", created_at: base_time) } let!(:merge_request_closed) { create(:merge_request, state: "closed", author: user, assignee: user, source_project: project, title: "Closed test", created_at: base_time + 1.second) } let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignee: user, source_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') } @@ -527,6 +526,18 @@ describe API::MergeRequests, api: true do expect(json_response['merge_when_pipeline_succeeds']).to eq(true) end + it "enables merge when pipeline succeeds if the pipeline is active and only_allow_merge_if_pipeline_succeeds is true" do + allow_any_instance_of(MergeRequest).to receive(:head_pipeline).and_return(pipeline) + allow(pipeline).to receive(:active?).and_return(true) + project.update_attribute(:only_allow_merge_if_pipeline_succeeds, true) + + put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), merge_when_pipeline_succeeds: true + + expect(response).to have_http_status(200) + expect(json_response['title']).to eq('Test') + expect(json_response['merge_when_pipeline_succeeds']).to eq(true) + end + it "returns 404 for an invalid merge request IID" do put api("/projects/#{project.id}/merge_requests/12345/merge", user) diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index 598968aff70..dd74351a2b1 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::Milestones, api: true do - include ApiHelpers +describe API::Milestones do let(:user) { create(:user) } let!(:project) { create(:empty_project, namespace: user.namespace ) } let!(:closed_milestone) { create(:closed_milestone, project: project, title: 'version1', description: 'closed milestone') } diff --git a/spec/requests/api/namespaces_spec.rb b/spec/requests/api/namespaces_spec.rb index da8fa06d0af..3bf16a3ae27 100644 --- a/spec/requests/api/namespaces_spec.rb +++ b/spec/requests/api/namespaces_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::Namespaces, api: true do - include ApiHelpers +describe API::Namespaces do let(:admin) { create(:admin) } let(:user) { create(:user) } let!(:group1) { create(:group) } diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index d8eb8ce921e..6afcd237c3c 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::Notes, api: true do - include ApiHelpers +describe API::Notes do let(:user) { create(:user) } let!(:project) { create(:empty_project, :public, namespace: user.namespace) } let!(:issue) { create(:issue, project: project, author: user) } diff --git a/spec/requests/api/notification_settings_spec.rb b/spec/requests/api/notification_settings_spec.rb index 39d3afcb78f..f619b7e6eaf 100644 --- a/spec/requests/api/notification_settings_spec.rb +++ b/spec/requests/api/notification_settings_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::NotificationSettings, api: true do - include ApiHelpers - +describe API::NotificationSettings do let(:user) { create(:user) } let!(:group) { create(:group) } let!(:project) { create(:empty_project, :public, creator_id: user.id, namespace: group) } diff --git a/spec/requests/api/oauth_tokens_spec.rb b/spec/requests/api/oauth_tokens_spec.rb index 367225df717..819df105960 100644 --- a/spec/requests/api/oauth_tokens_spec.rb +++ b/spec/requests/api/oauth_tokens_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::API, api: true do - include ApiHelpers - +describe API::API do context 'Resource Owner Password Credentials' do def request_oauth_token(user) post '/oauth/token', username: user.username, password: user.password, grant_type: 'password' diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb index 51af999b455..762345cd41c 100644 --- a/spec/requests/api/pipelines_spec.rb +++ b/spec/requests/api/pipelines_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Pipelines, api: true do - include ApiHelpers - +describe API::Pipelines do let(:user) { create(:user) } let(:non_member) { create(:user) } let(:project) { create(:project, :repository, creator: user) } diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb index b1603233f9e..aee0e17a153 100644 --- a/spec/requests/api/project_hooks_spec.rb +++ b/spec/requests/api/project_hooks_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::ProjectHooks, 'ProjectHooks', api: true do - include ApiHelpers +describe API::ProjectHooks, 'ProjectHooks' do let(:user) { create(:user) } let(:user3) { create(:user) } let!(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb index 9e88c19b0bc..3ab1764f5c3 100644 --- a/spec/requests/api/project_snippets_spec.rb +++ b/spec/requests/api/project_snippets_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' -describe API::ProjectSnippets, api: true do - include ApiHelpers - +describe API::ProjectSnippets do let(:project) { create(:empty_project, :public) } let(:user) { create(:user) } let(:admin) { create(:admin) } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 40365585a56..cc03d7a933b 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- require 'spec_helper' -describe API::Projects, :api do +describe API::Projects do include Gitlab::CurrentSettings let(:user) { create(:user) } diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index 4783d011d54..1a0695615e3 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -1,8 +1,7 @@ require 'spec_helper' require 'mime/types' -describe API::Repositories, api: true do - include ApiHelpers +describe API::Repositories do include RepoHelpers include WorkhorseHelpers diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index 409a59d6c23..be83514ed9c 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe API::Runner do - include ApiHelpers include StubGitlabCalls let(:registration_token) { 'abcdefg123456' } diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb index 8a82543a830..645a5389850 100644 --- a/spec/requests/api/runners_spec.rb +++ b/spec/requests/api/runners_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Runners, api: true do - include ApiHelpers - +describe API::Runners do let(:admin) { create(:user, :admin) } let(:user) { create(:user) } let(:user2) { create(:user) } diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index fd334934ca5..95df3429314 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -1,8 +1,6 @@ require "spec_helper" -describe API::Services, api: true do - include ApiHelpers - +describe API::Services do let(:user) { create(:user) } let(:admin) { create(:admin) } let(:user2) { create(:user) } diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb index 393bf076616..5e77519c867 100644 --- a/spec/requests/api/session_spec.rb +++ b/spec/requests/api/session_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Session, api: true do - include ApiHelpers - +describe API::Session do let(:user) { create(:user) } describe "POST /session" do diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index 11b4b718e2c..2398ae6219c 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Settings, 'Settings', api: true do - include ApiHelpers - +describe API::Settings, 'Settings' do let(:user) { create(:user) } let(:admin) { create(:admin) } diff --git a/spec/requests/api/sidekiq_metrics_spec.rb b/spec/requests/api/sidekiq_metrics_spec.rb index 28067f8ca88..83042d0cb12 100644 --- a/spec/requests/api/sidekiq_metrics_spec.rb +++ b/spec/requests/api/sidekiq_metrics_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::SidekiqMetrics, api: true do - include ApiHelpers - +describe API::SidekiqMetrics do let(:admin) { create(:user, :admin) } describe 'GET sidekiq/*' do diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb index 5d75b47b3cd..e429cddcf6a 100644 --- a/spec/requests/api/snippets_spec.rb +++ b/spec/requests/api/snippets_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' -describe API::Snippets, api: true do - include ApiHelpers +describe API::Snippets do let!(:user) { create(:user) } describe 'GET /snippets/' do diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb index d1e10f12657..c7b84173570 100644 --- a/spec/requests/api/system_hooks_spec.rb +++ b/spec/requests/api/system_hooks_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::SystemHooks, api: true do - include ApiHelpers - +describe API::SystemHooks do let(:user) { create(:user) } let(:admin) { create(:admin) } let!(:hook) { create(:system_hook, url: "http://example.com") } diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb index b132d033a61..ef7d0c3ee41 100644 --- a/spec/requests/api/tags_spec.rb +++ b/spec/requests/api/tags_spec.rb @@ -1,8 +1,7 @@ require 'spec_helper' require 'mime/types' -describe API::Tags, api: true do - include ApiHelpers +describe API::Tags do include RepoHelpers let(:user) { create(:user) } diff --git a/spec/requests/api/templates_spec.rb b/spec/requests/api/templates_spec.rb index 2c83e119065..cb55985e3f5 100644 --- a/spec/requests/api/templates_spec.rb +++ b/spec/requests/api/templates_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Templates, api: true do - include ApiHelpers - +describe API::Templates do context 'the Template Entity' do before { get api('/templates/gitignores/Ruby') } diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb index b789284fa8d..92533f4dfea 100644 --- a/spec/requests/api/todos_spec.rb +++ b/spec/requests/api/todos_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Todos, api: true do - include ApiHelpers - +describe API::Todos do let(:project_1) { create(:empty_project, :test_repo) } let(:project_2) { create(:empty_project) } let(:author_1) { create(:user) } diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb index d93a734f5b6..16ddade27d9 100644 --- a/spec/requests/api/triggers_spec.rb +++ b/spec/requests/api/triggers_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe API::Triggers do - include ApiHelpers - let(:user) { create(:user) } let(:user2) { create(:user) } let!(:trigger_token) { 'secure_token' } diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 165ab389917..2c6ae592d91 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -1,9 +1,7 @@ require 'spec_helper' -describe API::Users, api: true do - include ApiHelpers - - let(:user) { create(:user) } +describe API::Users do + let(:user) { create(:user) } let(:admin) { create(:admin) } let(:key) { create(:key, user: user) } let(:email) { create(:email, user: user) } diff --git a/spec/requests/api/v3/award_emoji_spec.rb b/spec/requests/api/v3/award_emoji_spec.rb index eeb4d128c1b..9234710f488 100644 --- a/spec/requests/api/v3/award_emoji_spec.rb +++ b/spec/requests/api/v3/award_emoji_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::AwardEmoji, api: true do - include ApiHelpers - +describe API::V3::AwardEmoji do let(:user) { create(:user) } let!(:project) { create(:empty_project) } let(:issue) { create(:issue, project: project) } diff --git a/spec/requests/api/v3/boards_spec.rb b/spec/requests/api/v3/boards_spec.rb index eb95934f354..4d786331d1b 100644 --- a/spec/requests/api/v3/boards_spec.rb +++ b/spec/requests/api/v3/boards_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Boards, api: true do - include ApiHelpers - +describe API::V3::Boards do let(:user) { create(:user) } let(:guest) { create(:user) } let(:non_member) { create(:user) } diff --git a/spec/requests/api/v3/branches_spec.rb b/spec/requests/api/v3/branches_spec.rb index 5dcd4f21f4e..72f8fbe71fb 100644 --- a/spec/requests/api/v3/branches_spec.rb +++ b/spec/requests/api/v3/branches_spec.rb @@ -1,9 +1,7 @@ require 'spec_helper' require 'mime/types' -describe API::V3::Branches, api: true do - include ApiHelpers - +describe API::V3::Branches do let(:user) { create(:user) } let(:user2) { create(:user) } let!(:project) { create(:project, :repository, creator: user) } diff --git a/spec/requests/api/v3/broadcast_messages_spec.rb b/spec/requests/api/v3/broadcast_messages_spec.rb index 06556401a29..948cd78c177 100644 --- a/spec/requests/api/v3/broadcast_messages_spec.rb +++ b/spec/requests/api/v3/broadcast_messages_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::BroadcastMessages, api: true do - include ApiHelpers - +describe API::V3::BroadcastMessages do let(:user) { create(:user) } let(:admin) { create(:admin) } diff --git a/spec/requests/api/v3/builds_spec.rb b/spec/requests/api/v3/builds_spec.rb index e97d2b0cee0..dc95599546c 100644 --- a/spec/requests/api/v3/builds_spec.rb +++ b/spec/requests/api/v3/builds_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Builds, api: true do - include ApiHelpers - +describe API::V3::Builds do let(:user) { create(:user) } let(:api_user) { user } let!(:project) { create(:project, :repository, creator: user, public_builds: false) } diff --git a/spec/requests/api/v3/commits_spec.rb b/spec/requests/api/v3/commits_spec.rb index 0a28cb9bddb..c2e8c3ae6f7 100644 --- a/spec/requests/api/v3/commits_spec.rb +++ b/spec/requests/api/v3/commits_spec.rb @@ -1,8 +1,7 @@ require 'spec_helper' require 'mime/types' -describe API::V3::Commits, api: true do - include ApiHelpers +describe API::V3::Commits do let(:user) { create(:user) } let(:user2) { create(:user) } let!(:project) { create(:project, :repository, creator: user, namespace: user.namespace) } diff --git a/spec/requests/api/v3/deploy_keys_spec.rb b/spec/requests/api/v3/deploy_keys_spec.rb index f5bdf408c5e..b61b2b618a6 100644 --- a/spec/requests/api/v3/deploy_keys_spec.rb +++ b/spec/requests/api/v3/deploy_keys_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::DeployKeys, api: true do - include ApiHelpers - +describe API::V3::DeployKeys do let(:user) { create(:user) } let(:admin) { create(:admin) } let(:project) { create(:empty_project, creator_id: user.id) } diff --git a/spec/requests/api/v3/deployments_spec.rb b/spec/requests/api/v3/deployments_spec.rb index 3c5ce407b32..694786c3046 100644 --- a/spec/requests/api/v3/deployments_spec.rb +++ b/spec/requests/api/v3/deployments_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Deployments, api: true do - include ApiHelpers - +describe API::Deployments do let(:user) { create(:user) } let(:non_member) { create(:user) } let(:project) { deployment.environment.project } diff --git a/spec/requests/api/v3/environments_spec.rb b/spec/requests/api/v3/environments_spec.rb index 216192c9d34..99f35723974 100644 --- a/spec/requests/api/v3/environments_spec.rb +++ b/spec/requests/api/v3/environments_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Environments, api: true do - include ApiHelpers - +describe API::V3::Environments do let(:user) { create(:user) } let(:non_member) { create(:user) } let(:project) { create(:empty_project, :private, namespace: user.namespace) } diff --git a/spec/requests/api/v3/files_spec.rb b/spec/requests/api/v3/files_spec.rb index c45e2028e1d..5bcbb441979 100644 --- a/spec/requests/api/v3/files_spec.rb +++ b/spec/requests/api/v3/files_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Files, api: true do - include ApiHelpers - +describe API::V3::Files do # I have to remove periods from the end of the name # This happened when the user's name had a suffix (i.e. "Sr.") # This seems to be what git does under the hood. For example, this commit: diff --git a/spec/requests/api/v3/groups_spec.rb b/spec/requests/api/v3/groups_spec.rb index a71b7d4b008..2862580cc70 100644 --- a/spec/requests/api/v3/groups_spec.rb +++ b/spec/requests/api/v3/groups_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::V3::Groups, api: true do - include ApiHelpers +describe API::V3::Groups do include UploadHelpers let(:user1) { create(:user, can_create_group: false) } diff --git a/spec/requests/api/v3/issues_spec.rb b/spec/requests/api/v3/issues_spec.rb index 91d9057075f..ef5b10a1615 100644 --- a/spec/requests/api/v3/issues_spec.rb +++ b/spec/requests/api/v3/issues_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::V3::Issues, api: true do - include ApiHelpers +describe API::V3::Issues do include EmailHelpers let(:user) { create(:user) } diff --git a/spec/requests/api/v3/labels_spec.rb b/spec/requests/api/v3/labels_spec.rb index dfac357d37c..62faa1cb129 100644 --- a/spec/requests/api/v3/labels_spec.rb +++ b/spec/requests/api/v3/labels_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Labels, api: true do - include ApiHelpers - +describe API::V3::Labels do let(:user) { create(:user) } let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } let!(:label1) { create(:label, title: 'label1', project: project) } diff --git a/spec/requests/api/v3/members_spec.rb b/spec/requests/api/v3/members_spec.rb index af1c5cff67f..623f02902b8 100644 --- a/spec/requests/api/v3/members_spec.rb +++ b/spec/requests/api/v3/members_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Members, api: true do - include ApiHelpers - +describe API::V3::Members do let(:master) { create(:user, username: 'master_user') } let(:developer) { create(:user) } let(:access_requester) { create(:user) } diff --git a/spec/requests/api/v3/merge_request_diffs_spec.rb b/spec/requests/api/v3/merge_request_diffs_spec.rb index c53800eef30..8020ddab4c8 100644 --- a/spec/requests/api/v3/merge_request_diffs_spec.rb +++ b/spec/requests/api/v3/merge_request_diffs_spec.rb @@ -1,8 +1,6 @@ require "spec_helper" -describe API::V3::MergeRequestDiffs, 'MergeRequestDiffs', api: true do - include ApiHelpers - +describe API::V3::MergeRequestDiffs, 'MergeRequestDiffs' do let!(:user) { create(:user) } let!(:merge_request) { create(:merge_request, importing: true) } let!(:project) { merge_request.target_project } diff --git a/spec/requests/api/v3/merge_requests_spec.rb b/spec/requests/api/v3/merge_requests_spec.rb index d73e9635c9b..6c2950a6e6f 100644 --- a/spec/requests/api/v3/merge_requests_spec.rb +++ b/spec/requests/api/v3/merge_requests_spec.rb @@ -1,7 +1,6 @@ require "spec_helper" -describe API::MergeRequests, api: true do - include ApiHelpers +describe API::MergeRequests do let(:base_time) { Time.now } let(:user) { create(:user) } let(:admin) { create(:user, :admin) } diff --git a/spec/requests/api/v3/milestones_spec.rb b/spec/requests/api/v3/milestones_spec.rb index 127c0eec881..f04efc990a7 100644 --- a/spec/requests/api/v3/milestones_spec.rb +++ b/spec/requests/api/v3/milestones_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::V3::Milestones, api: true do - include ApiHelpers +describe API::V3::Milestones do let(:user) { create(:user) } let!(:project) { create(:empty_project, namespace: user.namespace ) } let!(:closed_milestone) { create(:closed_milestone, project: project) } diff --git a/spec/requests/api/v3/notes_spec.rb b/spec/requests/api/v3/notes_spec.rb index ddef2d5eb04..2bae4a60931 100644 --- a/spec/requests/api/v3/notes_spec.rb +++ b/spec/requests/api/v3/notes_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Notes, api: true do - include ApiHelpers - +describe API::V3::Notes do let(:user) { create(:user) } let!(:project) { create(:empty_project, :public, namespace: user.namespace) } let!(:issue) { create(:issue, project: project, author: user) } diff --git a/spec/requests/api/v3/pipelines_spec.rb b/spec/requests/api/v3/pipelines_spec.rb index 3786eb06932..e1d036ff365 100644 --- a/spec/requests/api/v3/pipelines_spec.rb +++ b/spec/requests/api/v3/pipelines_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Pipelines, api: true do - include ApiHelpers - +describe API::V3::Pipelines do let(:user) { create(:user) } let(:non_member) { create(:user) } let(:project) { create(:project, :repository, creator: user) } diff --git a/spec/requests/api/v3/project_hooks_spec.rb b/spec/requests/api/v3/project_hooks_spec.rb index a981119dc5a..a3a4c77d09d 100644 --- a/spec/requests/api/v3/project_hooks_spec.rb +++ b/spec/requests/api/v3/project_hooks_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::ProjectHooks, 'ProjectHooks', api: true do - include ApiHelpers +describe API::ProjectHooks, 'ProjectHooks' do let(:user) { create(:user) } let(:user3) { create(:user) } let!(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } diff --git a/spec/requests/api/v3/project_snippets_spec.rb b/spec/requests/api/v3/project_snippets_spec.rb index 957a3bf97ef..365e7365fda 100644 --- a/spec/requests/api/v3/project_snippets_spec.rb +++ b/spec/requests/api/v3/project_snippets_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' -describe API::ProjectSnippets, api: true do - include ApiHelpers - +describe API::ProjectSnippets do let(:project) { create(:empty_project, :public) } let(:user) { create(:user) } let(:admin) { create(:admin) } diff --git a/spec/requests/api/v3/projects_spec.rb b/spec/requests/api/v3/projects_spec.rb index 40531fe7545..e15b90d7a9e 100644 --- a/spec/requests/api/v3/projects_spec.rb +++ b/spec/requests/api/v3/projects_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe API::V3::Projects, api: true do - include ApiHelpers +describe API::V3::Projects do include Gitlab::CurrentSettings let(:user) { create(:user) } diff --git a/spec/requests/api/v3/repositories_spec.rb b/spec/requests/api/v3/repositories_spec.rb index fef6fb641fa..1a55e2a71cd 100644 --- a/spec/requests/api/v3/repositories_spec.rb +++ b/spec/requests/api/v3/repositories_spec.rb @@ -1,8 +1,7 @@ require 'spec_helper' require 'mime/types' -describe API::V3::Repositories, api: true do - include ApiHelpers +describe API::V3::Repositories do include RepoHelpers include WorkhorseHelpers diff --git a/spec/requests/api/v3/runners_spec.rb b/spec/requests/api/v3/runners_spec.rb index ca335ce9cf0..dbda2cf34c3 100644 --- a/spec/requests/api/v3/runners_spec.rb +++ b/spec/requests/api/v3/runners_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Runners, api: true do - include ApiHelpers - +describe API::V3::Runners do let(:admin) { create(:user, :admin) } let(:user) { create(:user) } let(:user2) { create(:user) } diff --git a/spec/requests/api/v3/services_spec.rb b/spec/requests/api/v3/services_spec.rb index 3a760a8f25c..3ba62de822a 100644 --- a/spec/requests/api/v3/services_spec.rb +++ b/spec/requests/api/v3/services_spec.rb @@ -1,8 +1,6 @@ require "spec_helper" -describe API::V3::Services, api: true do - include ApiHelpers - +describe API::V3::Services do let(:user) { create(:user) } let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) } diff --git a/spec/requests/api/v3/settings_spec.rb b/spec/requests/api/v3/settings_spec.rb index a9fa5adac17..41d039b7da0 100644 --- a/spec/requests/api/v3/settings_spec.rb +++ b/spec/requests/api/v3/settings_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Settings, 'Settings', api: true do - include ApiHelpers - +describe API::V3::Settings, 'Settings' do let(:user) { create(:user) } let(:admin) { create(:admin) } diff --git a/spec/requests/api/v3/snippets_spec.rb b/spec/requests/api/v3/snippets_spec.rb index 05653bd0d51..4f02b7b1a54 100644 --- a/spec/requests/api/v3/snippets_spec.rb +++ b/spec/requests/api/v3/snippets_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' -describe API::V3::Snippets, api: true do - include ApiHelpers +describe API::V3::Snippets do let!(:user) { create(:user) } describe 'GET /snippets/' do diff --git a/spec/requests/api/v3/system_hooks_spec.rb b/spec/requests/api/v3/system_hooks_spec.rb index 91038977c82..72c7d14b8ba 100644 --- a/spec/requests/api/v3/system_hooks_spec.rb +++ b/spec/requests/api/v3/system_hooks_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::SystemHooks, api: true do - include ApiHelpers - +describe API::V3::SystemHooks do let(:user) { create(:user) } let(:admin) { create(:admin) } let!(:hook) { create(:system_hook, url: "http://example.com") } diff --git a/spec/requests/api/v3/tags_spec.rb b/spec/requests/api/v3/tags_spec.rb index 6870cfd2668..1c4b25c47c3 100644 --- a/spec/requests/api/v3/tags_spec.rb +++ b/spec/requests/api/v3/tags_spec.rb @@ -1,8 +1,7 @@ require 'spec_helper' require 'mime/types' -describe API::V3::Tags, api: true do - include ApiHelpers +describe API::V3::Tags do include RepoHelpers let(:user) { create(:user) } diff --git a/spec/requests/api/v3/templates_spec.rb b/spec/requests/api/v3/templates_spec.rb index f1e554b98cc..00446c7f29c 100644 --- a/spec/requests/api/v3/templates_spec.rb +++ b/spec/requests/api/v3/templates_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Templates, api: true do - include ApiHelpers - +describe API::V3::Templates do shared_examples_for 'the Template Entity' do |path| before { get v3_api(path) } diff --git a/spec/requests/api/v3/todos_spec.rb b/spec/requests/api/v3/todos_spec.rb index 80fa697e949..9c2c4d64257 100644 --- a/spec/requests/api/v3/todos_spec.rb +++ b/spec/requests/api/v3/todos_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Todos, api: true do - include ApiHelpers - +describe API::V3::Todos do let(:project_1) { create(:empty_project) } let(:project_2) { create(:empty_project) } let(:author_1) { create(:user) } diff --git a/spec/requests/api/v3/triggers_spec.rb b/spec/requests/api/v3/triggers_spec.rb index 9233e9621bf..d3de6bf13bc 100644 --- a/spec/requests/api/v3/triggers_spec.rb +++ b/spec/requests/api/v3/triggers_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe API::V3::Triggers do - include ApiHelpers - let(:user) { create(:user) } let(:user2) { create(:user) } let!(:trigger_token) { 'secure_token' } diff --git a/spec/requests/api/v3/users_spec.rb b/spec/requests/api/v3/users_spec.rb index b38cbe74b85..05ee704f738 100644 --- a/spec/requests/api/v3/users_spec.rb +++ b/spec/requests/api/v3/users_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Users, api: true do - include ApiHelpers - +describe API::V3::Users do let(:user) { create(:user) } let(:admin) { create(:admin) } let(:key) { create(:key, user: user) } diff --git a/spec/requests/api/variables_spec.rb b/spec/requests/api/variables_spec.rb index 0c1413119e0..63d6d3001ac 100644 --- a/spec/requests/api/variables_spec.rb +++ b/spec/requests/api/variables_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Variables, api: true do - include ApiHelpers - +describe API::Variables do let(:user) { create(:user) } let(:user2) { create(:user) } let!(:project) { create(:empty_project, creator_id: user.id) } diff --git a/spec/requests/api/version_spec.rb b/spec/requests/api/version_spec.rb index da1b2fda70e..8870d48bbc9 100644 --- a/spec/requests/api/version_spec.rb +++ b/spec/requests/api/version_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Version, api: true do - include ApiHelpers - +describe API::Version do describe 'GET /version' do context 'when unauthenticated' do it 'returns authentication error' do diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index ef30d8638dd..108f73bb965 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe Ci::API::Builds do - include ApiHelpers - let(:runner) { FactoryGirl.create(:ci_runner, tag_list: %w(mysql ruby)) } let(:project) { FactoryGirl.create(:empty_project, shared_runners_enabled: false) } let(:last_update) { nil } diff --git a/spec/requests/ci/api/runners_spec.rb b/spec/requests/ci/api/runners_spec.rb index d50cdfdc2d6..0b9733221d8 100644 --- a/spec/requests/ci/api/runners_spec.rb +++ b/spec/requests/ci/api/runners_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe Ci::API::Runners do - include ApiHelpers include StubGitlabCalls let(:registration_token) { 'abcdefg123456' } diff --git a/spec/requests/ci/api/triggers_spec.rb b/spec/requests/ci/api/triggers_spec.rb index 5321f8b134f..26b03c0f148 100644 --- a/spec/requests/ci/api/triggers_spec.rb +++ b/spec/requests/ci/api/triggers_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe Ci::API::Triggers do - include ApiHelpers - describe 'POST /projects/:project_id/refs/:ref/trigger' do let!(:trigger_token) { 'secure token' } let!(:project) { create(:project, :repository, ci_id: 10) } diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 316742ff076..6ca3ef18fe6 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -279,10 +279,10 @@ describe 'Git HTTP requests', lib: true do expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) end - it "uploads get status 401 (no project existence information leak)" do + it "uploads get status 200" do push_get "#{project.path_with_namespace}.git", user: 'oauth2', password: @token.token - expect(response).to have_http_status(401) + expect(response).to have_http_status(200) end end diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb index 5206634bca5..a4f85c22943 100644 --- a/spec/requests/openid_connect_spec.rb +++ b/spec/requests/openid_connect_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe 'OpenID Connect requests' do - include ApiHelpers - let(:user) { create :user } let(:access_grant) { create :oauth_access_grant, application: application, resource_owner_id: user.id } let(:access_token) { create :oauth_access_token, application: application, resource_owner_id: user.id } diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index 0edbffbcd3b..33940f70b1c 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe 'cycle analytics events' do - include ApiHelpers - +describe 'cycle analytics events', api: true do let(:user) { create(:user) } let(:project) { create(:project, :repository, public_builds: false) } let(:issue) { create(:issue, project: project, created_at: 2.days.ago) } diff --git a/spec/services/ci/expire_pipeline_cache_service_spec.rb b/spec/services/ci/expire_pipeline_cache_service_spec.rb deleted file mode 100644 index 166c6dfc93e..00000000000 --- a/spec/services/ci/expire_pipeline_cache_service_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'spec_helper' - -describe Ci::ExpirePipelineCacheService, services: true do - let(:user) { create(:user) } - let(:project) { create(:empty_project) } - let(:pipeline) { create(:ci_pipeline, project: project) } - subject { described_class.new(project, user) } - - describe '#execute' do - it 'invalidate Etag caching for project pipelines path' do - pipelines_path = "/#{project.full_path}/pipelines.json" - new_mr_pipelines_path = "/#{project.full_path}/merge_requests/new.json" - - expect_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch).with(pipelines_path) - expect_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch).with(new_mr_pipelines_path) - - subject.execute(pipeline) - end - - it 'updates the cached status for a project' do - expect(Gitlab::Cache::Ci::ProjectPipelineStatus).to receive(:update_for_pipeline). - with(pipeline) - - subject.execute(pipeline) - end - end -end diff --git a/spec/services/users/migrate_to_ghost_user_service_spec.rb b/spec/services/users/migrate_to_ghost_user_service_spec.rb index 8c5b7e41c15..9e1edf1ac30 100644 --- a/spec/services/users/migrate_to_ghost_user_service_spec.rb +++ b/spec/services/users/migrate_to_ghost_user_service_spec.rb @@ -60,5 +60,23 @@ describe Users::MigrateToGhostUserService, services: true do end end end + + context "when record migration fails with a rollback exception" do + before do + expect_any_instance_of(MergeRequest::ActiveRecord_Associations_CollectionProxy) + .to receive(:update_all).and_raise(ActiveRecord::Rollback) + end + + context "for records that were already migrated" do + let!(:issue) { create(:issue, project: project, author: user) } + let!(:merge_request) { create(:merge_request, source_project: project, author: user, target_branch: "first") } + + it "reverses the migration" do + service.execute + + expect(issue.reload.author).to eq(user) + end + end + end end end diff --git a/spec/support/features/issuable_slash_commands_shared_examples.rb b/spec/support/features/issuable_slash_commands_shared_examples.rb index a4713e53f63..5bbe36d9b7f 100644 --- a/spec/support/features/issuable_slash_commands_shared_examples.rb +++ b/spec/support/features/issuable_slash_commands_shared_examples.rb @@ -3,7 +3,6 @@ shared_examples 'issuable record that supports slash commands in its description and notes' do |issuable_type| include SlashCommandsHelpers - include WaitForAjax let(:master) { create(:user) } let(:assignee) { create(:user, username: 'bob') } diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index 9ffb00be0b8..e6da852e728 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -84,8 +84,4 @@ module LoginHelpers def logout_direct page.driver.submit :delete, '/users/sign_out', {} end - - def skip_ci_admin_auth - allow_any_instance_of(Ci::Admin::ApplicationController).to receive_messages(authenticate_admin!: true) - end end diff --git a/spec/support/markdown_feature.rb b/spec/support/markdown_feature.rb index dea0015f105..21a054af4e1 100644 --- a/spec/support/markdown_feature.rb +++ b/spec/support/markdown_feature.rb @@ -23,7 +23,7 @@ class MarkdownFeature # Direct references ---------------------------------------------------------- def project - @project ||= create(:project).tap do |project| + @project ||= create(:project, :repository).tap do |project| project.team << [user, :master] end end @@ -80,7 +80,7 @@ class MarkdownFeature def xproject @xproject ||= begin group = create(:group, :nested) - create(:project, namespace: group) do |project| + create(:project, :repository, namespace: group) do |project| project.team << [user, :developer] end end diff --git a/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb b/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb index 0eac587e973..dcc562c684b 100644 --- a/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb +++ b/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb @@ -35,5 +35,57 @@ shared_examples "migrating a deleted user's associated records to the ghost user expect(user).to be_blocked end + + context "race conditions" do + context "when #{record_class_name} migration fails and is rolled back" do + before do + expect_any_instance_of(record_class::ActiveRecord_Associations_CollectionProxy) + .to receive(:update_all).and_raise(ActiveRecord::Rollback) + end + + it 'rolls back the user block' do + service.execute + + expect(user.reload).not_to be_blocked + end + + it "doesn't unblock an previously-blocked user" do + user.block + + service.execute + + expect(user.reload).to be_blocked + end + end + + context "when #{record_class_name} migration fails with a non-rollback exception" do + before do + expect_any_instance_of(record_class::ActiveRecord_Associations_CollectionProxy) + .to receive(:update_all).and_raise(ArgumentError) + end + + it 'rolls back the user block' do + service.execute rescue nil + + expect(user.reload).not_to be_blocked + end + + it "doesn't unblock an previously-blocked user" do + user.block + + service.execute rescue nil + + expect(user.reload).to be_blocked + end + end + + it "blocks the user before #{record_class_name} migration begins" do + expect(service).to receive("migrate_#{record_class_name.parameterize('_')}s".to_sym) do + expect(user.reload).to be_blocked + end + + service.execute + end + end end end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 60c2096a126..eb0f1efe55b 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -38,7 +38,8 @@ module TestEnv 'deleted-image-test' => '6c17798', 'wip' => 'b9238ee', 'csv' => '3dd0896', - 'v1.1.0' => 'b83d6e3' + 'v1.1.0' => 'b83d6e3', + 'add-ipython-files' => '6d85bb69' }.freeze # gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily diff --git a/spec/support/wait_for_ajax.rb b/spec/support/wait_for_ajax.rb index 0f9dc2dee75..508de2ee8e1 100644 --- a/spec/support/wait_for_ajax.rb +++ b/spec/support/wait_for_ajax.rb @@ -6,10 +6,13 @@ module WaitForAjax end def finished_all_ajax_requests? + return true unless javascript_test? + return true if page.evaluate_script('typeof jQuery === "undefined"') + page.evaluate_script('jQuery.active').zero? end def javascript_test? - [:selenium, :webkit, :chrome, :poltergeist].include?(Capybara.current_driver) + Capybara.current_driver == Capybara.javascript_driver end end diff --git a/spec/views/projects/_last_commit.html.haml_spec.rb b/spec/views/projects/_last_commit.html.haml_spec.rb new file mode 100644 index 00000000000..eea1695b171 --- /dev/null +++ b/spec/views/projects/_last_commit.html.haml_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe 'projects/_last_commit', :view do + let(:project) { create(:project, :repository) } + + context 'when there is a pipeline present for the commit' do + context 'when pipeline is blocked' do + let!(:pipeline) do + create(:ci_pipeline, :blocked, project: project, + sha: project.commit.id) + end + + it 'shows correct pipeline badge' do + render 'projects/last_commit', commit: project.commit, + project: project, + ref: :master + + expect(rendered).to have_text "blocked #{project.commit.short_id}" + end + end + end +end diff --git a/spec/views/projects/commit/_commit_box.html.haml_spec.rb b/spec/views/projects/commit/_commit_box.html.haml_spec.rb index cec87dcecc8..ab120929c6c 100644 --- a/spec/views/projects/commit/_commit_box.html.haml_spec.rb +++ b/spec/views/projects/commit/_commit_box.html.haml_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe 'projects/commit/_commit_box.html.haml' do - include Devise::Test::ControllerHelpers - +describe 'projects/commit/_commit_box.html.haml', :view do let(:user) { create(:user) } let(:project) { create(:project, :repository) } @@ -18,14 +16,32 @@ describe 'projects/commit/_commit_box.html.haml' do expect(rendered).to have_text("#{Commit.truncate_sha(project.commit.sha)}") end - it 'shows the last pipeline that ran for the commit' do - create(:ci_pipeline, project: project, sha: project.commit.id, status: 'success') - create(:ci_pipeline, project: project, sha: project.commit.id, status: 'canceled') - third_pipeline = create(:ci_pipeline, project: project, sha: project.commit.id, status: 'failed') + context 'when there is a pipeline present' do + context 'when there are multiple pipelines for a commit' do + it 'shows the last pipeline' do + create(:ci_pipeline, project: project, sha: project.commit.id, status: 'success') + create(:ci_pipeline, project: project, sha: project.commit.id, status: 'canceled') + third_pipeline = create(:ci_pipeline, project: project, sha: project.commit.id, status: 'failed') - render + render + + expect(rendered).to have_text("Pipeline ##{third_pipeline.id} failed") + end + end - expect(rendered).to have_text("Pipeline ##{third_pipeline.id} failed") + context 'when pipeline for the commit is blocked' do + let!(:pipeline) do + create(:ci_pipeline, :blocked, project: project, + sha: project.commit.id) + end + + it 'shows correct pipeline description' do + render + + expect(rendered).to have_text "Pipeline ##{pipeline.id} " \ + 'waiting for manual action' + end + end end context 'viewing a commit' do diff --git a/spec/workers/expire_pipeline_cache_worker_spec.rb b/spec/workers/expire_pipeline_cache_worker_spec.rb new file mode 100644 index 00000000000..ceba604dea2 --- /dev/null +++ b/spec/workers/expire_pipeline_cache_worker_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe ExpirePipelineCacheWorker do + let(:user) { create(:user) } + let(:project) { create(:empty_project) } + let(:pipeline) { create(:ci_pipeline, project: project) } + subject { described_class.new } + + describe '#perform' do + it 'invalidates Etag caching for project pipelines path' do + pipelines_path = "/#{project.full_path}/pipelines.json" + new_mr_pipelines_path = "/#{project.full_path}/merge_requests/new.json" + + expect_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch).with(pipelines_path) + expect_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch).with(new_mr_pipelines_path) + + subject.perform(pipeline.id) + end + + it 'invalidates Etag caching for merge request pipelines if pipeline runs on any commit of that source branch' do + pipeline = create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master') + merge_request = create(:merge_request, source_project: project, source_branch: pipeline.ref) + merge_request_pipelines_path = "/#{project.full_path}/merge_requests/#{merge_request.iid}/pipelines.json" + + allow_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch) + expect_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch).with(merge_request_pipelines_path) + + subject.perform(pipeline.id) + end + + it "doesn't do anything if the pipeline not exist" do + expect_any_instance_of(Gitlab::EtagCaching::Store).not_to receive(:touch) + + subject.perform(617748) + end + + it 'updates the cached status for a project' do + expect(Gitlab::Cache::Ci::ProjectPipelineStatus).to receive(:update_for_pipeline). + with(pipeline) + + subject.perform(pipeline.id) + end + end +end diff --git a/vendor/assets/javascripts/notebooklab.js b/vendor/assets/javascripts/notebooklab.js deleted file mode 100644 index b8cfdc53b48..00000000000 --- a/vendor/assets/javascripts/notebooklab.js +++ /dev/null @@ -1,5733 +0,0 @@ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define("NotebookLab", [], factory); - else if(typeof exports === 'object') - exports["NotebookLab"] = factory(); - else - root["NotebookLab"] = factory(); -})(this, function() { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; -/******/ -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // identity function for calling harmony imports with the correct context -/******/ __webpack_require__.i = function(value) { return value; }; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 47); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, exports) { - -// this module is a runtime utility for cleaner component module output and will -// be included in the final webpack user bundle - -module.exports = function normalizeComponent ( - rawScriptExports, - compiledTemplate, - scopeId, - cssModules -) { - var esModule - var scriptExports = rawScriptExports = rawScriptExports || {} - - // ES6 modules interop - var type = typeof rawScriptExports.default - if (type === 'object' || type === 'function') { - esModule = rawScriptExports - scriptExports = rawScriptExports.default - } - - // Vue.extend constructor export interop - var options = typeof scriptExports === 'function' - ? scriptExports.options - : scriptExports - - // render functions - if (compiledTemplate) { - options.render = compiledTemplate.render - options.staticRenderFns = compiledTemplate.staticRenderFns - } - - // scopedId - if (scopeId) { - options._scopeId = scopeId - } - - // inject cssModules - if (cssModules) { - var computed = Object.create(options.computed || null) - Object.keys(cssModules).forEach(function (key) { - var module = cssModules[key] - computed[key] = function () { return module } - }) - options.computed = computed - } - - return { - esModule: esModule, - exports: scriptExports, - options: options - } -} - - -/***/ }), -/* 1 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(Buffer) {/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -// css base code, injected by the css-loader -module.exports = function(useSourceMap) { - var list = []; - - // return the list of modules as css string - list.toString = function toString() { - return this.map(function (item) { - var content = cssWithMappingToString(item, useSourceMap); - if(item[2]) { - return "@media " + item[2] + "{" + content + "}"; - } else { - return content; - } - }).join(""); - }; - - // import a list of modules into the list - list.i = function(modules, mediaQuery) { - if(typeof modules === "string") - modules = [[null, modules, ""]]; - var alreadyImportedModules = {}; - for(var i = 0; i < this.length; i++) { - var id = this[i][0]; - if(typeof id === "number") - alreadyImportedModules[id] = true; - } - for(i = 0; i < modules.length; i++) { - var item = modules[i]; - // skip already imported module - // this implementation is not 100% perfect for weird media query combinations - // when a module is imported multiple times with different media queries. - // I hope this will never occur (Hey this way we have smaller bundles) - if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) { - if(mediaQuery && !item[2]) { - item[2] = mediaQuery; - } else if(mediaQuery) { - item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; - } - list.push(item); - } - } - }; - return list; -}; - -function cssWithMappingToString(item, useSourceMap) { - var content = item[1] || ''; - var cssMapping = item[3]; - if (!cssMapping) { - return content; - } - - if (useSourceMap) { - var sourceMapping = toComment(cssMapping); - var sourceURLs = cssMapping.sources.map(function (source) { - return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */' - }); - - return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); - } - - return [content].join('\n'); -} - -// Adapted from convert-source-map (MIT) -function toComment(sourceMap) { - var base64 = new Buffer(JSON.stringify(sourceMap)).toString('base64'); - var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64; - - return '/*# ' + data + ' */'; -} - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(18).Buffer)) - -/***/ }), -/* 2 */ -/***/ (function(module, exports, __webpack_require__) { - - -/* styles */ -__webpack_require__(44) - -var Component = __webpack_require__(0)( - /* script */ - __webpack_require__(13), - /* template */ - __webpack_require__(39), - /* scopeId */ - "data-v-4f6bf458", - /* cssModules */ - null -) - -module.exports = Component.exports - - -/***/ }), -/* 3 */ -/***/ (function(module, exports, __webpack_require__) { - -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra - Modified by Evan You @yyx990803 -*/ - -var hasDocument = typeof document !== 'undefined' - -if (typeof DEBUG !== 'undefined' && DEBUG) { - if (!hasDocument) { - throw new Error( - 'vue-style-loader cannot be used in a non-browser environment. ' + - "Use { target: 'node' } in your Webpack config to indicate a server-rendering environment." - ) } -} - -var listToStyles = __webpack_require__(46) - -/* -type StyleObject = { - id: number; - parts: Array<StyleObjectPart> -} - -type StyleObjectPart = { - css: string; - media: string; - sourceMap: ?string -} -*/ - -var stylesInDom = {/* - [id: number]: { - id: number, - refs: number, - parts: Array<(obj?: StyleObjectPart) => void> - } -*/} - -var head = hasDocument && (document.head || document.getElementsByTagName('head')[0]) -var singletonElement = null -var singletonCounter = 0 -var isProduction = false -var noop = function () {} - -// Force single-tag solution on IE6-9, which has a hard limit on the # of <style> -// tags it will allow on a page -var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\b/.test(navigator.userAgent.toLowerCase()) - -module.exports = function (parentId, list, _isProduction) { - isProduction = _isProduction - - var styles = listToStyles(parentId, list) - addStylesToDom(styles) - - return function update (newList) { - var mayRemove = [] - for (var i = 0; i < styles.length; i++) { - var item = styles[i] - var domStyle = stylesInDom[item.id] - domStyle.refs-- - mayRemove.push(domStyle) - } - if (newList) { - styles = listToStyles(parentId, newList) - addStylesToDom(styles) - } else { - styles = [] - } - for (var i = 0; i < mayRemove.length; i++) { - var domStyle = mayRemove[i] - if (domStyle.refs === 0) { - for (var j = 0; j < domStyle.parts.length; j++) { - domStyle.parts[j]() - } - delete stylesInDom[domStyle.id] - } - } - } -} - -function addStylesToDom (styles /* Array<StyleObject> */) { - for (var i = 0; i < styles.length; i++) { - var item = styles[i] - var domStyle = stylesInDom[item.id] - if (domStyle) { - domStyle.refs++ - for (var j = 0; j < domStyle.parts.length; j++) { - domStyle.parts[j](item.parts[j]) - } - for (; j < item.parts.length; j++) { - domStyle.parts.push(addStyle(item.parts[j])) - } - if (domStyle.parts.length > item.parts.length) { - domStyle.parts.length = item.parts.length - } - } else { - var parts = [] - for (var j = 0; j < item.parts.length; j++) { - parts.push(addStyle(item.parts[j])) - } - stylesInDom[item.id] = { id: item.id, refs: 1, parts: parts } - } - } -} - -function createStyleElement () { - var styleElement = document.createElement('style') - styleElement.type = 'text/css' - head.appendChild(styleElement) - return styleElement -} - -function addStyle (obj /* StyleObjectPart */) { - var update, remove - var styleElement = document.querySelector('style[data-vue-ssr-id~="' + obj.id + '"]') - - if (styleElement) { - if (isProduction) { - // has SSR styles and in production mode. - // simply do nothing. - return noop - } else { - // has SSR styles but in dev mode. - // for some reason Chrome can't handle source map in server-rendered - // style tags - source maps in <style> only works if the style tag is - // created and inserted dynamically. So we remove the server rendered - // styles and inject new ones. - styleElement.parentNode.removeChild(styleElement) - } - } - - if (isOldIE) { - // use singleton mode for IE9. - var styleIndex = singletonCounter++ - styleElement = singletonElement || (singletonElement = createStyleElement()) - update = applyToSingletonTag.bind(null, styleElement, styleIndex, false) - remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true) - } else { - // use multi-style-tag mode in all other cases - styleElement = createStyleElement() - update = applyToTag.bind(null, styleElement) - remove = function () { - styleElement.parentNode.removeChild(styleElement) - } - } - - update(obj) - - return function updateStyle (newObj /* StyleObjectPart */) { - if (newObj) { - if (newObj.css === obj.css && - newObj.media === obj.media && - newObj.sourceMap === obj.sourceMap) { - return - } - update(obj = newObj) - } else { - remove() - } - } -} - -var replaceText = (function () { - var textStore = [] - - return function (index, replacement) { - textStore[index] = replacement - return textStore.filter(Boolean).join('\n') - } -})() - -function applyToSingletonTag (styleElement, index, remove, obj) { - var css = remove ? '' : obj.css - - if (styleElement.styleSheet) { - styleElement.styleSheet.cssText = replaceText(index, css) - } else { - var cssNode = document.createTextNode(css) - var childNodes = styleElement.childNodes - if (childNodes[index]) styleElement.removeChild(childNodes[index]) - if (childNodes.length) { - styleElement.insertBefore(cssNode, childNodes[index]) - } else { - styleElement.appendChild(cssNode) - } - } -} - -function applyToTag (styleElement, obj) { - var css = obj.css - var media = obj.media - var sourceMap = obj.sourceMap - - if (media) { - styleElement.setAttribute('media', media) - } - - if (sourceMap) { - // https://developer.chrome.com/devtools/docs/javascript-debugging - // this makes source maps inside style tags work properly in Chrome - css += '\n/*# sourceURL=' + sourceMap.sources[0] + ' */' - // http://stackoverflow.com/a/26603875 - css += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + ' */' - } - - if (styleElement.styleSheet) { - styleElement.styleSheet.cssText = css - } else { - while (styleElement.firstChild) { - styleElement.removeChild(styleElement.firstChild) - } - styleElement.appendChild(document.createTextNode(css)) - } -} - - -/***/ }), -/* 4 */ -/***/ (function(module, exports) { - -var g;
-
-// This works in non-strict mode
-g = (function() {
- return this;
-})();
-
-try {
- // This works if eval is allowed (see CSP)
- g = g || Function("return this")() || (1,eval)("this");
-} catch(e) {
- // This works if the window reference is available
- if(typeof window === "object")
- g = window;
-}
-
-// g can still be undefined, but nothing to do about it...
-// We return undefined, instead of nothing here, so it's
-// easier to handle this case. if(!global) { ...}
-
-module.exports = g;
- - -/***/ }), -/* 5 */ -/***/ (function(module, exports, __webpack_require__) { - -var Component = __webpack_require__(0)( - /* script */ - __webpack_require__(8), - /* template */ - __webpack_require__(41), - /* scopeId */ - null, - /* cssModules */ - null -) - -module.exports = Component.exports - - -/***/ }), -/* 6 */ -/***/ (function(module, exports, __webpack_require__) { - - -/* styles */ -__webpack_require__(43) - -var Component = __webpack_require__(0)( - /* script */ - __webpack_require__(14), - /* template */ - __webpack_require__(38), - /* scopeId */ - null, - /* cssModules */ - null -) - -module.exports = Component.exports - - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _index = __webpack_require__(5); - -var _index2 = _interopRequireDefault(_index); - -var _index3 = __webpack_require__(33); - -var _index4 = _interopRequireDefault(_index3); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// - -exports.default = { - components: { - 'code-cell': _index2.default, - 'output-cell': _index4.default - }, - props: { - cell: { - type: Object, - required: true - }, - codeCssClass: { - type: String, - required: false, - default: '' - } - }, - computed: { - rawInputCode: function rawInputCode() { - if (this.cell.source) { - return this.cell.source.join(''); - } - - return ''; - }, - hasOutput: function hasOutput() { - return this.cell.outputs.length; - }, - output: function output() { - return this.cell.outputs[0]; - } - } -}; - -/***/ }), -/* 8 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _highlight = __webpack_require__(16); - -var _highlight2 = _interopRequireDefault(_highlight); - -var _prompt = __webpack_require__(2); - -var _prompt2 = _interopRequireDefault(_prompt); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// -// -// -// -// -// -// -// -// -// -// -// -// -// - -exports.default = { - components: { - prompt: _prompt2.default - }, - props: { - count: { - type: Number, - required: false, - default: 0 - }, - codeCssClass: { - type: String, - required: false, - default: '' - }, - type: { - type: String, - required: true - }, - rawCode: { - type: String, - required: true - } - }, - computed: { - code: function code() { - return this.rawCode; - }, - promptType: function promptType() { - var type = this.type.split('put')[0]; - - return type.charAt(0).toUpperCase() + type.slice(1); - } - }, - mounted: function mounted() { - _highlight2.default.highlightElement(this.$refs.code); - } -}; - -/***/ }), -/* 9 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _marked = __webpack_require__(25); - -var _marked2 = _interopRequireDefault(_marked); - -var _prompt = __webpack_require__(2); - -var _prompt2 = _interopRequireDefault(_prompt); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// -// -// -// -// -// -// - -var renderer = new _marked2.default.Renderer(); - -/* - Regex to match KaTex blocks. - - Supports the following: - - \begin{equation}<math>\end{equation} - $$<math>$$ - inline $<math>$ - - The matched text then goes through the KaTex renderer & then outputs the HTML -*/ -var katexRegexString = '(\n ^\\\\begin{[a-zA-Z]+}\\s\n |\n ^\\$\\$\n |\n \\s\\$(?!\\$)\n)\n (.+?)\n(\n \\s\\\\end{[a-zA-Z]+}$\n |\n \\$\\$$\n |\n \\$\n)\n'.replace(/\s/g, '').trim(); - -renderer.paragraph = function (t) { - var text = t; - var inline = false; - - if (typeof katex !== 'undefined') { - var katexString = text.replace(/\\/g, '\\'); - var matches = new RegExp(katexRegexString, 'gi').exec(katexString); - - if (matches && matches.length > 0) { - if (matches[1].trim() === '$' && matches[3].trim() === '$') { - inline = true; - - text = katexString.replace(matches[0], '') + ' ' + katex.renderToString(matches[2]); - } else { - text = katex.renderToString(matches[2]); - } - } - } - - return '<p class="' + (inline ? 'inline-katex' : '') + '">' + text + '</p>'; -}; - -_marked2.default.setOptions({ - sanitize: true, - renderer: renderer -}); - -exports.default = { - components: { - prompt: _prompt2.default - }, - props: { - cell: { - type: Object, - required: true - } - }, - computed: { - markdown: function markdown() { - return (0, _marked2.default)(this.cell.source.join('')); - } - } -}; - -/***/ }), -/* 10 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _prompt = __webpack_require__(2); - -var _prompt2 = _interopRequireDefault(_prompt); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = { - props: { - rawCode: { - type: String, - required: true - } - }, - components: { - prompt: _prompt2.default - } -}; // -// -// -// -// -// -// - -/***/ }), -/* 11 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _prompt = __webpack_require__(2); - -var _prompt2 = _interopRequireDefault(_prompt); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = { - props: { - outputType: { - type: String, - required: true - }, - rawCode: { - type: String, - required: true - } - }, - components: { - prompt: _prompt2.default - } -}; // -// -// -// -// -// -// -// - -/***/ }), -/* 12 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; // -// -// -// -// -// -// -// -// - -var _index = __webpack_require__(5); - -var _index2 = _interopRequireDefault(_index); - -var _html = __webpack_require__(31); - -var _html2 = _interopRequireDefault(_html); - -var _image = __webpack_require__(32); - -var _image2 = _interopRequireDefault(_image); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = { - props: { - codeCssClass: { - type: String, - required: false, - default: '' - }, - count: { - type: Number, - required: false, - default: 0 - }, - output: { - type: Object, - requred: true - } - }, - components: { - 'code-cell': _index2.default, - 'html-output': _html2.default, - 'image-output': _image2.default - }, - data: function data() { - return { - outputType: '' - }; - }, - - computed: { - componentName: function componentName() { - if (this.output.text) { - return 'code-cell'; - } else if (this.output.data['image/png']) { - this.outputType = 'image/png'; - - return 'image-output'; - } else if (this.output.data['text/html']) { - this.outputType = 'text/html'; - - return 'html-output'; - } else if (this.output.data['image/svg+xml']) { - this.outputType = 'image/svg+xml'; - - return 'html-output'; - } - - this.outputType = 'text/plain'; - return 'code-cell'; - }, - rawCode: function rawCode() { - if (this.output.text) { - return this.output.text.join(''); - } - - return this.dataForType(this.outputType); - } - }, - methods: { - dataForType: function dataForType(type) { - var data = this.output.data[type]; - - if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object') { - data = data.join(''); - } - - return data; - } - } -}; - -/***/ }), -/* 13 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -// -// -// -// -// -// -// -// - -exports.default = { - props: { - type: { - type: String, - required: false - }, - count: { - type: Number, - required: false - } - } -}; - -/***/ }), -/* 14 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _cells = __webpack_require__(15); - -exports.default = { - components: { - 'code-cell': _cells.CodeCell, - 'markdown-cell': _cells.MarkdownCell - }, - props: { - notebook: { - type: Object, - required: true - }, - codeCssClass: { - type: String, - required: false, - default: '' - } - }, - methods: { - cellType: function cellType(type) { - return type + '-cell'; - } - }, - computed: { - cells: function cells() { - if (this.notebook.worksheets) { - var data = { - cells: [] - }; - - return this.notebook.worksheets.reduce(function (cellData, sheet) { - var cellDataCopy = cellData; - cellDataCopy.cells = cellDataCopy.cells.concat(sheet.cells); - return cellDataCopy; - }, data).cells; - } - - return this.notebook.cells; - }, - hasNotebook: function hasNotebook() { - return Object.keys(this.notebook).length; - } - } -}; // -// -// -// -// -// -// -// -// -// -// - -/***/ }), -/* 15 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _markdown = __webpack_require__(30); - -Object.defineProperty(exports, 'MarkdownCell', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_markdown).default; - } -}); - -var _code = __webpack_require__(29); - -Object.defineProperty(exports, 'CodeCell', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_code).default; - } -}); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/***/ }), -/* 16 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _prismjs = __webpack_require__(28); - -var _prismjs2 = _interopRequireDefault(_prismjs); - -__webpack_require__(26); - -__webpack_require__(27); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_prismjs2.default.plugins.customClass.map({ - comment: 'c', - error: 'err', - operator: 'o', - constant: 'kc', - namespace: 'kn', - keyword: 'k', - string: 's', - number: 'm', - 'attr-name': 'na', - builtin: 'nb', - entity: 'ni', - function: 'nf', - tag: 'nt', - variable: 'nv' -}); - -exports.default = _prismjs2.default; - -/***/ }), -/* 17 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -exports.byteLength = byteLength -exports.toByteArray = toByteArray -exports.fromByteArray = fromByteArray - -var lookup = [] -var revLookup = [] -var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array - -var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -for (var i = 0, len = code.length; i < len; ++i) { - lookup[i] = code[i] - revLookup[code.charCodeAt(i)] = i -} - -revLookup['-'.charCodeAt(0)] = 62 -revLookup['_'.charCodeAt(0)] = 63 - -function placeHoldersCount (b64) { - var len = b64.length - if (len % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // the number of equal signs (place holders) - // if there are two placeholders, than the two characters before it - // represent one byte - // if there is only one, then the three characters before it represent 2 bytes - // this is just a cheap hack to not do indexOf twice - return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 -} - -function byteLength (b64) { - // base64 is 4/3 + up to two characters of the original data - return b64.length * 3 / 4 - placeHoldersCount(b64) -} - -function toByteArray (b64) { - var i, j, l, tmp, placeHolders, arr - var len = b64.length - placeHolders = placeHoldersCount(b64) - - arr = new Arr(len * 3 / 4 - placeHolders) - - // if there are placeholders, only get up to the last complete 4 chars - l = placeHolders > 0 ? len - 4 : len - - var L = 0 - - for (i = 0, j = 0; i < l; i += 4, j += 3) { - tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] - arr[L++] = (tmp >> 16) & 0xFF - arr[L++] = (tmp >> 8) & 0xFF - arr[L++] = tmp & 0xFF - } - - if (placeHolders === 2) { - tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) - arr[L++] = tmp & 0xFF - } else if (placeHolders === 1) { - tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[L++] = (tmp >> 8) & 0xFF - arr[L++] = tmp & 0xFF - } - - return arr -} - -function tripletToBase64 (num) { - return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] -} - -function encodeChunk (uint8, start, end) { - var tmp - var output = [] - for (var i = start; i < end; i += 3) { - tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) - output.push(tripletToBase64(tmp)) - } - return output.join('') -} - -function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var output = '' - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 - - // go through the array every three bytes, we'll deal with trailing stuff later - for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - if (extraBytes === 1) { - tmp = uint8[len - 1] - output += lookup[tmp >> 2] - output += lookup[(tmp << 4) & 0x3F] - output += '==' - } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) - output += lookup[tmp >> 10] - output += lookup[(tmp >> 4) & 0x3F] - output += lookup[(tmp << 2) & 0x3F] - output += '=' - } - - parts.push(output) - - return parts.join('') -} - - -/***/ }), -/* 18 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/* WEBPACK VAR INJECTION */(function(global) {/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> - * @license MIT - */ -/* eslint-disable no-proto */ - - - -var base64 = __webpack_require__(17) -var ieee754 = __webpack_require__(23) -var isArray = __webpack_require__(24) - -exports.Buffer = Buffer -exports.SlowBuffer = SlowBuffer -exports.INSPECT_MAX_BYTES = 50 - -/** - * If `Buffer.TYPED_ARRAY_SUPPORT`: - * === true Use Uint8Array implementation (fastest) - * === false Use Object implementation (most compatible, even IE6) - * - * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, - * Opera 11.6+, iOS 4.2+. - * - * Due to various browser bugs, sometimes the Object implementation will be used even - * when the browser supports typed arrays. - * - * Note: - * - * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, - * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. - * - * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. - * - * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of - * incorrect length in some situations. - - * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they - * get the Object implementation, which is slower but behaves correctly. - */ -Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined - ? global.TYPED_ARRAY_SUPPORT - : typedArraySupport() - -/* - * Export kMaxLength after typed array support is determined. - */ -exports.kMaxLength = kMaxLength() - -function typedArraySupport () { - try { - var arr = new Uint8Array(1) - arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} - return arr.foo() === 42 && // typed array instances can be augmented - typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` - arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` - } catch (e) { - return false - } -} - -function kMaxLength () { - return Buffer.TYPED_ARRAY_SUPPORT - ? 0x7fffffff - : 0x3fffffff -} - -function createBuffer (that, length) { - if (kMaxLength() < length) { - throw new RangeError('Invalid typed array length') - } - if (Buffer.TYPED_ARRAY_SUPPORT) { - // Return an augmented `Uint8Array` instance, for best performance - that = new Uint8Array(length) - that.__proto__ = Buffer.prototype - } else { - // Fallback: Return an object instance of the Buffer class - if (that === null) { - that = new Buffer(length) - } - that.length = length - } - - return that -} - -/** - * The Buffer constructor returns instances of `Uint8Array` that have their - * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of - * `Uint8Array`, so the returned instances will have all the node `Buffer` methods - * and the `Uint8Array` methods. Square bracket notation works as expected -- it - * returns a single octet. - * - * The `Uint8Array` prototype remains unmodified. - */ - -function Buffer (arg, encodingOrOffset, length) { - if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { - return new Buffer(arg, encodingOrOffset, length) - } - - // Common case. - if (typeof arg === 'number') { - if (typeof encodingOrOffset === 'string') { - throw new Error( - 'If encoding is specified then the first argument must be a string' - ) - } - return allocUnsafe(this, arg) - } - return from(this, arg, encodingOrOffset, length) -} - -Buffer.poolSize = 8192 // not used by this implementation - -// TODO: Legacy, not needed anymore. Remove in next major version. -Buffer._augment = function (arr) { - arr.__proto__ = Buffer.prototype - return arr -} - -function from (that, value, encodingOrOffset, length) { - if (typeof value === 'number') { - throw new TypeError('"value" argument must not be a number') - } - - if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { - return fromArrayBuffer(that, value, encodingOrOffset, length) - } - - if (typeof value === 'string') { - return fromString(that, value, encodingOrOffset) - } - - return fromObject(that, value) -} - -/** - * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError - * if value is a number. - * Buffer.from(str[, encoding]) - * Buffer.from(array) - * Buffer.from(buffer) - * Buffer.from(arrayBuffer[, byteOffset[, length]]) - **/ -Buffer.from = function (value, encodingOrOffset, length) { - return from(null, value, encodingOrOffset, length) -} - -if (Buffer.TYPED_ARRAY_SUPPORT) { - Buffer.prototype.__proto__ = Uint8Array.prototype - Buffer.__proto__ = Uint8Array - if (typeof Symbol !== 'undefined' && Symbol.species && - Buffer[Symbol.species] === Buffer) { - // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 - Object.defineProperty(Buffer, Symbol.species, { - value: null, - configurable: true - }) - } -} - -function assertSize (size) { - if (typeof size !== 'number') { - throw new TypeError('"size" argument must be a number') - } else if (size < 0) { - throw new RangeError('"size" argument must not be negative') - } -} - -function alloc (that, size, fill, encoding) { - assertSize(size) - if (size <= 0) { - return createBuffer(that, size) - } - if (fill !== undefined) { - // Only pay attention to encoding if it's a string. This - // prevents accidentally sending in a number that would - // be interpretted as a start offset. - return typeof encoding === 'string' - ? createBuffer(that, size).fill(fill, encoding) - : createBuffer(that, size).fill(fill) - } - return createBuffer(that, size) -} - -/** - * Creates a new filled Buffer instance. - * alloc(size[, fill[, encoding]]) - **/ -Buffer.alloc = function (size, fill, encoding) { - return alloc(null, size, fill, encoding) -} - -function allocUnsafe (that, size) { - assertSize(size) - that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) { - for (var i = 0; i < size; ++i) { - that[i] = 0 - } - } - return that -} - -/** - * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. - * */ -Buffer.allocUnsafe = function (size) { - return allocUnsafe(null, size) -} -/** - * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. - */ -Buffer.allocUnsafeSlow = function (size) { - return allocUnsafe(null, size) -} - -function fromString (that, string, encoding) { - if (typeof encoding !== 'string' || encoding === '') { - encoding = 'utf8' - } - - if (!Buffer.isEncoding(encoding)) { - throw new TypeError('"encoding" must be a valid string encoding') - } - - var length = byteLength(string, encoding) | 0 - that = createBuffer(that, length) - - var actual = that.write(string, encoding) - - if (actual !== length) { - // Writing a hex string, for example, that contains invalid characters will - // cause everything after the first invalid character to be ignored. (e.g. - // 'abxxcd' will be treated as 'ab') - that = that.slice(0, actual) - } - - return that -} - -function fromArrayLike (that, array) { - var length = array.length < 0 ? 0 : checked(array.length) | 0 - that = createBuffer(that, length) - for (var i = 0; i < length; i += 1) { - that[i] = array[i] & 255 - } - return that -} - -function fromArrayBuffer (that, array, byteOffset, length) { - array.byteLength // this throws if `array` is not a valid ArrayBuffer - - if (byteOffset < 0 || array.byteLength < byteOffset) { - throw new RangeError('\'offset\' is out of bounds') - } - - if (array.byteLength < byteOffset + (length || 0)) { - throw new RangeError('\'length\' is out of bounds') - } - - if (byteOffset === undefined && length === undefined) { - array = new Uint8Array(array) - } else if (length === undefined) { - array = new Uint8Array(array, byteOffset) - } else { - array = new Uint8Array(array, byteOffset, length) - } - - if (Buffer.TYPED_ARRAY_SUPPORT) { - // Return an augmented `Uint8Array` instance, for best performance - that = array - that.__proto__ = Buffer.prototype - } else { - // Fallback: Return an object instance of the Buffer class - that = fromArrayLike(that, array) - } - return that -} - -function fromObject (that, obj) { - if (Buffer.isBuffer(obj)) { - var len = checked(obj.length) | 0 - that = createBuffer(that, len) - - if (that.length === 0) { - return that - } - - obj.copy(that, 0, 0, len) - return that - } - - if (obj) { - if ((typeof ArrayBuffer !== 'undefined' && - obj.buffer instanceof ArrayBuffer) || 'length' in obj) { - if (typeof obj.length !== 'number' || isnan(obj.length)) { - return createBuffer(that, 0) - } - return fromArrayLike(that, obj) - } - - if (obj.type === 'Buffer' && isArray(obj.data)) { - return fromArrayLike(that, obj.data) - } - } - - throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') -} - -function checked (length) { - // Note: cannot use `length < kMaxLength()` here because that fails when - // length is NaN (which is otherwise coerced to zero.) - if (length >= kMaxLength()) { - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + kMaxLength().toString(16) + ' bytes') - } - return length | 0 -} - -function SlowBuffer (length) { - if (+length != length) { // eslint-disable-line eqeqeq - length = 0 - } - return Buffer.alloc(+length) -} - -Buffer.isBuffer = function isBuffer (b) { - return !!(b != null && b._isBuffer) -} - -Buffer.compare = function compare (a, b) { - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { - throw new TypeError('Arguments must be Buffers') - } - - if (a === b) return 0 - - var x = a.length - var y = b.length - - for (var i = 0, len = Math.min(x, y); i < len; ++i) { - if (a[i] !== b[i]) { - x = a[i] - y = b[i] - break - } - } - - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -Buffer.isEncoding = function isEncoding (encoding) { - switch (String(encoding).toLowerCase()) { - case 'hex': - case 'utf8': - case 'utf-8': - case 'ascii': - case 'latin1': - case 'binary': - case 'base64': - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return true - default: - return false - } -} - -Buffer.concat = function concat (list, length) { - if (!isArray(list)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - - if (list.length === 0) { - return Buffer.alloc(0) - } - - var i - if (length === undefined) { - length = 0 - for (i = 0; i < list.length; ++i) { - length += list[i].length - } - } - - var buffer = Buffer.allocUnsafe(length) - var pos = 0 - for (i = 0; i < list.length; ++i) { - var buf = list[i] - if (!Buffer.isBuffer(buf)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - buf.copy(buffer, pos) - pos += buf.length - } - return buffer -} - -function byteLength (string, encoding) { - if (Buffer.isBuffer(string)) { - return string.length - } - if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && - (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { - return string.byteLength - } - if (typeof string !== 'string') { - string = '' + string - } - - var len = string.length - if (len === 0) return 0 - - // Use a for loop to avoid recursion - var loweredCase = false - for (;;) { - switch (encoding) { - case 'ascii': - case 'latin1': - case 'binary': - return len - case 'utf8': - case 'utf-8': - case undefined: - return utf8ToBytes(string).length - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return len * 2 - case 'hex': - return len >>> 1 - case 'base64': - return base64ToBytes(string).length - default: - if (loweredCase) return utf8ToBytes(string).length // assume utf8 - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } - } -} -Buffer.byteLength = byteLength - -function slowToString (encoding, start, end) { - var loweredCase = false - - // No need to verify that "this.length <= MAX_UINT32" since it's a read-only - // property of a typed array. - - // This behaves neither like String nor Uint8Array in that we set start/end - // to their upper/lower bounds if the value passed is out of range. - // undefined is handled specially as per ECMA-262 6th Edition, - // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. - if (start === undefined || start < 0) { - start = 0 - } - // Return early if start > this.length. Done here to prevent potential uint32 - // coercion fail below. - if (start > this.length) { - return '' - } - - if (end === undefined || end > this.length) { - end = this.length - } - - if (end <= 0) { - return '' - } - - // Force coersion to uint32. This will also coerce falsey/NaN values to 0. - end >>>= 0 - start >>>= 0 - - if (end <= start) { - return '' - } - - if (!encoding) encoding = 'utf8' - - while (true) { - switch (encoding) { - case 'hex': - return hexSlice(this, start, end) - - case 'utf8': - case 'utf-8': - return utf8Slice(this, start, end) - - case 'ascii': - return asciiSlice(this, start, end) - - case 'latin1': - case 'binary': - return latin1Slice(this, start, end) - - case 'base64': - return base64Slice(this, start, end) - - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return utf16leSlice(this, start, end) - - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = (encoding + '').toLowerCase() - loweredCase = true - } - } -} - -// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect -// Buffer instances. -Buffer.prototype._isBuffer = true - -function swap (b, n, m) { - var i = b[n] - b[n] = b[m] - b[m] = i -} - -Buffer.prototype.swap16 = function swap16 () { - var len = this.length - if (len % 2 !== 0) { - throw new RangeError('Buffer size must be a multiple of 16-bits') - } - for (var i = 0; i < len; i += 2) { - swap(this, i, i + 1) - } - return this -} - -Buffer.prototype.swap32 = function swap32 () { - var len = this.length - if (len % 4 !== 0) { - throw new RangeError('Buffer size must be a multiple of 32-bits') - } - for (var i = 0; i < len; i += 4) { - swap(this, i, i + 3) - swap(this, i + 1, i + 2) - } - return this -} - -Buffer.prototype.swap64 = function swap64 () { - var len = this.length - if (len % 8 !== 0) { - throw new RangeError('Buffer size must be a multiple of 64-bits') - } - for (var i = 0; i < len; i += 8) { - swap(this, i, i + 7) - swap(this, i + 1, i + 6) - swap(this, i + 2, i + 5) - swap(this, i + 3, i + 4) - } - return this -} - -Buffer.prototype.toString = function toString () { - var length = this.length | 0 - if (length === 0) return '' - if (arguments.length === 0) return utf8Slice(this, 0, length) - return slowToString.apply(this, arguments) -} - -Buffer.prototype.equals = function equals (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - if (this === b) return true - return Buffer.compare(this, b) === 0 -} - -Buffer.prototype.inspect = function inspect () { - var str = '' - var max = exports.INSPECT_MAX_BYTES - if (this.length > 0) { - str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') - if (this.length > max) str += ' ... ' - } - return '<Buffer ' + str + '>' -} - -Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { - if (!Buffer.isBuffer(target)) { - throw new TypeError('Argument must be a Buffer') - } - - if (start === undefined) { - start = 0 - } - if (end === undefined) { - end = target ? target.length : 0 - } - if (thisStart === undefined) { - thisStart = 0 - } - if (thisEnd === undefined) { - thisEnd = this.length - } - - if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { - throw new RangeError('out of range index') - } - - if (thisStart >= thisEnd && start >= end) { - return 0 - } - if (thisStart >= thisEnd) { - return -1 - } - if (start >= end) { - return 1 - } - - start >>>= 0 - end >>>= 0 - thisStart >>>= 0 - thisEnd >>>= 0 - - if (this === target) return 0 - - var x = thisEnd - thisStart - var y = end - start - var len = Math.min(x, y) - - var thisCopy = this.slice(thisStart, thisEnd) - var targetCopy = target.slice(start, end) - - for (var i = 0; i < len; ++i) { - if (thisCopy[i] !== targetCopy[i]) { - x = thisCopy[i] - y = targetCopy[i] - break - } - } - - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, -// OR the last index of `val` in `buffer` at offset <= `byteOffset`. -// -// Arguments: -// - buffer - a Buffer to search -// - val - a string, Buffer, or number -// - byteOffset - an index into `buffer`; will be clamped to an int32 -// - encoding - an optional encoding, relevant is val is a string -// - dir - true for indexOf, false for lastIndexOf -function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { - // Empty buffer means no match - if (buffer.length === 0) return -1 - - // Normalize byteOffset - if (typeof byteOffset === 'string') { - encoding = byteOffset - byteOffset = 0 - } else if (byteOffset > 0x7fffffff) { - byteOffset = 0x7fffffff - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000 - } - byteOffset = +byteOffset // Coerce to Number. - if (isNaN(byteOffset)) { - // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer - byteOffset = dir ? 0 : (buffer.length - 1) - } - - // Normalize byteOffset: negative offsets start from the end of the buffer - if (byteOffset < 0) byteOffset = buffer.length + byteOffset - if (byteOffset >= buffer.length) { - if (dir) return -1 - else byteOffset = buffer.length - 1 - } else if (byteOffset < 0) { - if (dir) byteOffset = 0 - else return -1 - } - - // Normalize val - if (typeof val === 'string') { - val = Buffer.from(val, encoding) - } - - // Finally, search either indexOf (if dir is true) or lastIndexOf - if (Buffer.isBuffer(val)) { - // Special case: looking for empty string/buffer always fails - if (val.length === 0) { - return -1 - } - return arrayIndexOf(buffer, val, byteOffset, encoding, dir) - } else if (typeof val === 'number') { - val = val & 0xFF // Search for a byte value [0-255] - if (Buffer.TYPED_ARRAY_SUPPORT && - typeof Uint8Array.prototype.indexOf === 'function') { - if (dir) { - return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) - } else { - return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) - } - } - return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) - } - - throw new TypeError('val must be string, number or Buffer') -} - -function arrayIndexOf (arr, val, byteOffset, encoding, dir) { - var indexSize = 1 - var arrLength = arr.length - var valLength = val.length - - if (encoding !== undefined) { - encoding = String(encoding).toLowerCase() - if (encoding === 'ucs2' || encoding === 'ucs-2' || - encoding === 'utf16le' || encoding === 'utf-16le') { - if (arr.length < 2 || val.length < 2) { - return -1 - } - indexSize = 2 - arrLength /= 2 - valLength /= 2 - byteOffset /= 2 - } - } - - function read (buf, i) { - if (indexSize === 1) { - return buf[i] - } else { - return buf.readUInt16BE(i * indexSize) - } - } - - var i - if (dir) { - var foundIndex = -1 - for (i = byteOffset; i < arrLength; i++) { - if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { - if (foundIndex === -1) foundIndex = i - if (i - foundIndex + 1 === valLength) return foundIndex * indexSize - } else { - if (foundIndex !== -1) i -= i - foundIndex - foundIndex = -1 - } - } - } else { - if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength - for (i = byteOffset; i >= 0; i--) { - var found = true - for (var j = 0; j < valLength; j++) { - if (read(arr, i + j) !== read(val, j)) { - found = false - break - } - } - if (found) return i - } - } - - return -1 -} - -Buffer.prototype.includes = function includes (val, byteOffset, encoding) { - return this.indexOf(val, byteOffset, encoding) !== -1 -} - -Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, true) -} - -Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, false) -} - -function hexWrite (buf, string, offset, length) { - offset = Number(offset) || 0 - var remaining = buf.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } - } - - // must be an even number of digits - var strLen = string.length - if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') - - if (length > strLen / 2) { - length = strLen / 2 - } - for (var i = 0; i < length; ++i) { - var parsed = parseInt(string.substr(i * 2, 2), 16) - if (isNaN(parsed)) return i - buf[offset + i] = parsed - } - return i -} - -function utf8Write (buf, string, offset, length) { - return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) -} - -function asciiWrite (buf, string, offset, length) { - return blitBuffer(asciiToBytes(string), buf, offset, length) -} - -function latin1Write (buf, string, offset, length) { - return asciiWrite(buf, string, offset, length) -} - -function base64Write (buf, string, offset, length) { - return blitBuffer(base64ToBytes(string), buf, offset, length) -} - -function ucs2Write (buf, string, offset, length) { - return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) -} - -Buffer.prototype.write = function write (string, offset, length, encoding) { - // Buffer#write(string) - if (offset === undefined) { - encoding = 'utf8' - length = this.length - offset = 0 - // Buffer#write(string, encoding) - } else if (length === undefined && typeof offset === 'string') { - encoding = offset - length = this.length - offset = 0 - // Buffer#write(string, offset[, length][, encoding]) - } else if (isFinite(offset)) { - offset = offset | 0 - if (isFinite(length)) { - length = length | 0 - if (encoding === undefined) encoding = 'utf8' - } else { - encoding = length - length = undefined - } - // legacy write(string, encoding, offset, length) - remove in v0.13 - } else { - throw new Error( - 'Buffer.write(string, encoding, offset[, length]) is no longer supported' - ) - } - - var remaining = this.length - offset - if (length === undefined || length > remaining) length = remaining - - if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { - throw new RangeError('Attempt to write outside buffer bounds') - } - - if (!encoding) encoding = 'utf8' - - var loweredCase = false - for (;;) { - switch (encoding) { - case 'hex': - return hexWrite(this, string, offset, length) - - case 'utf8': - case 'utf-8': - return utf8Write(this, string, offset, length) - - case 'ascii': - return asciiWrite(this, string, offset, length) - - case 'latin1': - case 'binary': - return latin1Write(this, string, offset, length) - - case 'base64': - // Warning: maxLength not taken into account in base64Write - return base64Write(this, string, offset, length) - - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return ucs2Write(this, string, offset, length) - - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } - } -} - -Buffer.prototype.toJSON = function toJSON () { - return { - type: 'Buffer', - data: Array.prototype.slice.call(this._arr || this, 0) - } -} - -function base64Slice (buf, start, end) { - if (start === 0 && end === buf.length) { - return base64.fromByteArray(buf) - } else { - return base64.fromByteArray(buf.slice(start, end)) - } -} - -function utf8Slice (buf, start, end) { - end = Math.min(buf.length, end) - var res = [] - - var i = start - while (i < end) { - var firstByte = buf[i] - var codePoint = null - var bytesPerSequence = (firstByte > 0xEF) ? 4 - : (firstByte > 0xDF) ? 3 - : (firstByte > 0xBF) ? 2 - : 1 - - if (i + bytesPerSequence <= end) { - var secondByte, thirdByte, fourthByte, tempCodePoint - - switch (bytesPerSequence) { - case 1: - if (firstByte < 0x80) { - codePoint = firstByte - } - break - case 2: - secondByte = buf[i + 1] - if ((secondByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) - if (tempCodePoint > 0x7F) { - codePoint = tempCodePoint - } - } - break - case 3: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) - if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { - codePoint = tempCodePoint - } - } - break - case 4: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - fourthByte = buf[i + 3] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) - if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { - codePoint = tempCodePoint - } - } - } - } - - if (codePoint === null) { - // we did not generate a valid codePoint so insert a - // replacement char (U+FFFD) and advance only 1 byte - codePoint = 0xFFFD - bytesPerSequence = 1 - } else if (codePoint > 0xFFFF) { - // encode to utf16 (surrogate pair dance) - codePoint -= 0x10000 - res.push(codePoint >>> 10 & 0x3FF | 0xD800) - codePoint = 0xDC00 | codePoint & 0x3FF - } - - res.push(codePoint) - i += bytesPerSequence - } - - return decodeCodePointsArray(res) -} - -// Based on http://stackoverflow.com/a/22747272/680742, the browser with -// the lowest limit is Chrome, with 0x10000 args. -// We go 1 magnitude less, for safety -var MAX_ARGUMENTS_LENGTH = 0x1000 - -function decodeCodePointsArray (codePoints) { - var len = codePoints.length - if (len <= MAX_ARGUMENTS_LENGTH) { - return String.fromCharCode.apply(String, codePoints) // avoid extra slice() - } - - // Decode in chunks to avoid "call stack size exceeded". - var res = '' - var i = 0 - while (i < len) { - res += String.fromCharCode.apply( - String, - codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) - ) - } - return res -} - -function asciiSlice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i] & 0x7F) - } - return ret -} - -function latin1Slice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i]) - } - return ret -} - -function hexSlice (buf, start, end) { - var len = buf.length - - if (!start || start < 0) start = 0 - if (!end || end < 0 || end > len) end = len - - var out = '' - for (var i = start; i < end; ++i) { - out += toHex(buf[i]) - } - return out -} - -function utf16leSlice (buf, start, end) { - var bytes = buf.slice(start, end) - var res = '' - for (var i = 0; i < bytes.length; i += 2) { - res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) - } - return res -} - -Buffer.prototype.slice = function slice (start, end) { - var len = this.length - start = ~~start - end = end === undefined ? len : ~~end - - if (start < 0) { - start += len - if (start < 0) start = 0 - } else if (start > len) { - start = len - } - - if (end < 0) { - end += len - if (end < 0) end = 0 - } else if (end > len) { - end = len - } - - if (end < start) end = start - - var newBuf - if (Buffer.TYPED_ARRAY_SUPPORT) { - newBuf = this.subarray(start, end) - newBuf.__proto__ = Buffer.prototype - } else { - var sliceLen = end - start - newBuf = new Buffer(sliceLen, undefined) - for (var i = 0; i < sliceLen; ++i) { - newBuf[i] = this[i + start] - } - } - - return newBuf -} - -/* - * Need to make sure that buffer isn't trying to write out of bounds. - */ -function checkOffset (offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') - if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') -} - -Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } - - return val -} - -Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) { - checkOffset(offset, byteLength, this.length) - } - - var val = this[offset + --byteLength] - var mul = 1 - while (byteLength > 0 && (mul *= 0x100)) { - val += this[offset + --byteLength] * mul - } - - return val -} - -Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { - if (!noAssert) checkOffset(offset, 1, this.length) - return this[offset] -} - -Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - return this[offset] | (this[offset + 1] << 8) -} - -Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - return (this[offset] << 8) | this[offset + 1] -} - -Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - - return ((this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16)) + - (this[offset + 3] * 0x1000000) -} - -Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset] * 0x1000000) + - ((this[offset + 1] << 16) | - (this[offset + 2] << 8) | - this[offset + 3]) -} - -Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - var i = byteLength - var mul = 1 - var val = this[offset + --i] - while (i > 0 && (mul *= 0x100)) { - val += this[offset + --i] * mul - } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { - if (!noAssert) checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) return (this[offset]) - return ((0xff - this[offset] + 1) * -1) -} - -Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset] | (this[offset + 1] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset + 1] | (this[offset] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16) | - (this[offset + 3] << 24) -} - -Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset] << 24) | - (this[offset + 1] << 16) | - (this[offset + 2] << 8) | - (this[offset + 3]) -} - -Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, true, 23, 4) -} - -Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, false, 23, 4) -} - -Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, true, 52, 8) -} - -Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, false, 52, 8) -} - -function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') - if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') - if (offset + ext > buf.length) throw new RangeError('Index out of range') -} - -Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } - - var mul = 1 - var i = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } - - var i = byteLength - 1 - var mul = 1 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - this[offset] = (value & 0xff) - return offset + 1 -} - -function objectWriteUInt16 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { - buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> - (littleEndian ? i : 1 - i) * 8 - } -} - -Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - } else { - objectWriteUInt16(this, value, offset, true) - } - return offset + 2 -} - -Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - } else { - objectWriteUInt16(this, value, offset, false) - } - return offset + 2 -} - -function objectWriteUInt32 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffffffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { - buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff - } -} - -Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) - this[offset] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, true) - } - return offset + 4 -} - -Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, false) - } - return offset + 4 -} - -Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) { - var limit = Math.pow(2, 8 * byteLength - 1) - - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } - - var i = 0 - var mul = 1 - var sub = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { - sub = 1 - } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) { - var limit = Math.pow(2, 8 * byteLength - 1) - - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } - - var i = byteLength - 1 - var mul = 1 - var sub = 0 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { - sub = 1 - } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - if (value < 0) value = 0xff + value + 1 - this[offset] = (value & 0xff) - return offset + 1 -} - -Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - } else { - objectWriteUInt16(this, value, offset, true) - } - return offset + 2 -} - -Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - } else { - objectWriteUInt16(this, value, offset, false) - } - return offset + 2 -} - -Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) - this[offset + 3] = (value >>> 24) - } else { - objectWriteUInt32(this, value, offset, true) - } - return offset + 4 -} - -Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (value < 0) value = 0xffffffff + value + 1 - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, false) - } - return offset + 4 -} - -function checkIEEE754 (buf, value, offset, ext, max, min) { - if (offset + ext > buf.length) throw new RangeError('Index out of range') - if (offset < 0) throw new RangeError('Index out of range') -} - -function writeFloat (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) - } - ieee754.write(buf, value, offset, littleEndian, 23, 4) - return offset + 4 -} - -Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { - return writeFloat(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { - return writeFloat(this, value, offset, false, noAssert) -} - -function writeDouble (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) - } - ieee754.write(buf, value, offset, littleEndian, 52, 8) - return offset + 8 -} - -Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { - return writeDouble(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { - return writeDouble(this, value, offset, false, noAssert) -} - -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function copy (target, targetStart, start, end) { - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (targetStart >= target.length) targetStart = target.length - if (!targetStart) targetStart = 0 - if (end > 0 && end < start) end = start - - // Copy 0 bytes; we're done - if (end === start) return 0 - if (target.length === 0 || this.length === 0) return 0 - - // Fatal error conditions - if (targetStart < 0) { - throw new RangeError('targetStart out of bounds') - } - if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') - if (end < 0) throw new RangeError('sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) end = this.length - if (target.length - targetStart < end - start) { - end = target.length - targetStart + start - } - - var len = end - start - var i - - if (this === target && start < targetStart && targetStart < end) { - // descending copy from end - for (i = len - 1; i >= 0; --i) { - target[i + targetStart] = this[i + start] - } - } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { - // ascending copy from start - for (i = 0; i < len; ++i) { - target[i + targetStart] = this[i + start] - } - } else { - Uint8Array.prototype.set.call( - target, - this.subarray(start, start + len), - targetStart - ) - } - - return len -} - -// Usage: -// buffer.fill(number[, offset[, end]]) -// buffer.fill(buffer[, offset[, end]]) -// buffer.fill(string[, offset[, end]][, encoding]) -Buffer.prototype.fill = function fill (val, start, end, encoding) { - // Handle string cases: - if (typeof val === 'string') { - if (typeof start === 'string') { - encoding = start - start = 0 - end = this.length - } else if (typeof end === 'string') { - encoding = end - end = this.length - } - if (val.length === 1) { - var code = val.charCodeAt(0) - if (code < 256) { - val = code - } - } - if (encoding !== undefined && typeof encoding !== 'string') { - throw new TypeError('encoding must be a string') - } - if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) - } - } else if (typeof val === 'number') { - val = val & 255 - } - - // Invalid ranges are not set to a default, so can range check early. - if (start < 0 || this.length < start || this.length < end) { - throw new RangeError('Out of range index') - } - - if (end <= start) { - return this - } - - start = start >>> 0 - end = end === undefined ? this.length : end >>> 0 - - if (!val) val = 0 - - var i - if (typeof val === 'number') { - for (i = start; i < end; ++i) { - this[i] = val - } - } else { - var bytes = Buffer.isBuffer(val) - ? val - : utf8ToBytes(new Buffer(val, encoding).toString()) - var len = bytes.length - for (i = 0; i < end - start; ++i) { - this[i + start] = bytes[i % len] - } - } - - return this -} - -// HELPER FUNCTIONS -// ================ - -var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g - -function base64clean (str) { - // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = stringtrim(str).replace(INVALID_BASE64_RE, '') - // Node converts strings with length < 2 to '' - if (str.length < 2) return '' - // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not - while (str.length % 4 !== 0) { - str = str + '=' - } - return str -} - -function stringtrim (str) { - if (str.trim) return str.trim() - return str.replace(/^\s+|\s+$/g, '') -} - -function toHex (n) { - if (n < 16) return '0' + n.toString(16) - return n.toString(16) -} - -function utf8ToBytes (string, units) { - units = units || Infinity - var codePoint - var length = string.length - var leadSurrogate = null - var bytes = [] - - for (var i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i) - - // is surrogate component - if (codePoint > 0xD7FF && codePoint < 0xE000) { - // last char was a lead - if (!leadSurrogate) { - // no lead yet - if (codePoint > 0xDBFF) { - // unexpected trail - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } else if (i + 1 === length) { - // unpaired lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } - - // valid lead - leadSurrogate = codePoint - - continue - } - - // 2 leads in a row - if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = codePoint - continue - } - - // valid surrogate pair - codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 - } else if (leadSurrogate) { - // valid bmp char, but last char was a lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - } - - leadSurrogate = null - - // encode utf8 - if (codePoint < 0x80) { - if ((units -= 1) < 0) break - bytes.push(codePoint) - } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break - bytes.push( - codePoint >> 0x6 | 0xC0, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break - bytes.push( - codePoint >> 0xC | 0xE0, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break - bytes.push( - codePoint >> 0x12 | 0xF0, - codePoint >> 0xC & 0x3F | 0x80, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else { - throw new Error('Invalid code point') - } - } - - return bytes -} - -function asciiToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - // Node's code seems to be doing this and not & 0x7F.. - byteArray.push(str.charCodeAt(i) & 0xFF) - } - return byteArray -} - -function utf16leToBytes (str, units) { - var c, hi, lo - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - if ((units -= 2) < 0) break - - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) - byteArray.push(hi) - } - - return byteArray -} - -function base64ToBytes (str) { - return base64.toByteArray(base64clean(str)) -} - -function blitBuffer (src, dst, offset, length) { - for (var i = 0; i < length; ++i) { - if ((i + offset >= dst.length) || (i >= src.length)) break - dst[i + offset] = src[i] - } - return i -} - -function isnan (val) { - return val !== val // eslint-disable-line no-self-compare -} - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4))) - -/***/ }), -/* 19 */ -/***/ (function(module, exports, __webpack_require__) { - -exports = module.exports = __webpack_require__(1)(undefined); -// imports - - -// module -exports.push([module.i, ".cell[data-v-3ac4c361]{flex-direction:column}", ""]); - -// exports - - -/***/ }), -/* 20 */ -/***/ (function(module, exports, __webpack_require__) { - -exports = module.exports = __webpack_require__(1)(undefined); -// imports - - -// module -exports.push([module.i, ".cell,.input,.output{display:flex;width:100%;margin-bottom:10px}.cell pre{margin:0;width:100%}", ""]); - -// exports - - -/***/ }), -/* 21 */ -/***/ (function(module, exports, __webpack_require__) { - -exports = module.exports = __webpack_require__(1)(undefined); -// imports - - -// module -exports.push([module.i, ".prompt[data-v-4f6bf458]{padding:0 10px;min-width:7em;font-family:monospace}", ""]); - -// exports - - -/***/ }), -/* 22 */ -/***/ (function(module, exports, __webpack_require__) { - -exports = module.exports = __webpack_require__(1)(undefined); -// imports - - -// module -exports.push([module.i, ".markdown .katex{display:block;text-align:center}.markdown .inline-katex .katex{display:inline;text-align:initial}", ""]); - -// exports - - -/***/ }), -/* 23 */ -/***/ (function(module, exports) { - -exports.read = function (buffer, offset, isLE, mLen, nBytes) { - var e, m - var eLen = nBytes * 8 - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var nBits = -7 - var i = isLE ? (nBytes - 1) : 0 - var d = isLE ? -1 : 1 - var s = buffer[offset + i] - - i += d - - e = s & ((1 << (-nBits)) - 1) - s >>= (-nBits) - nBits += eLen - for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} - - m = e & ((1 << (-nBits)) - 1) - e >>= (-nBits) - nBits += mLen - for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} - - if (e === 0) { - e = 1 - eBias - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity) - } else { - m = m + Math.pow(2, mLen) - e = e - eBias - } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen) -} - -exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { - var e, m, c - var eLen = nBytes * 8 - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) - var i = isLE ? 0 : (nBytes - 1) - var d = isLE ? 1 : -1 - var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 - - value = Math.abs(value) - - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0 - e = eMax - } else { - e = Math.floor(Math.log(value) / Math.LN2) - if (value * (c = Math.pow(2, -e)) < 1) { - e-- - c *= 2 - } - if (e + eBias >= 1) { - value += rt / c - } else { - value += rt * Math.pow(2, 1 - eBias) - } - if (value * c >= 2) { - e++ - c /= 2 - } - - if (e + eBias >= eMax) { - m = 0 - e = eMax - } else if (e + eBias >= 1) { - m = (value * c - 1) * Math.pow(2, mLen) - e = e + eBias - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) - e = 0 - } - } - - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} - - e = (e << mLen) | m - eLen += mLen - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} - - buffer[offset + i - d] |= s * 128 -} - - -/***/ }), -/* 24 */ -/***/ (function(module, exports) { - -var toString = {}.toString; - -module.exports = Array.isArray || function (arr) { - return toString.call(arr) == '[object Array]'; -}; - - -/***/ }), -/* 25 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global) {/** - * marked - a markdown parser - * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) - * https://github.com/chjj/marked - */ - -;(function() { - -/** - * Block-Level Grammar - */ - -var block = { - newline: /^\n+/, - code: /^( {4}[^\n]+\n*)+/, - fences: noop, - hr: /^( *[-*_]){3,} *(?:\n+|$)/, - heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, - nptable: noop, - lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, - blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, - list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, - html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, - def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, - table: noop, - paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, - text: /^[^\n]+/ -}; - -block.bullet = /(?:[*+-]|\d+\.)/; -block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; -block.item = replace(block.item, 'gm') - (/bull/g, block.bullet) - (); - -block.list = replace(block.list) - (/bull/g, block.bullet) - ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))') - ('def', '\\n+(?=' + block.def.source + ')') - (); - -block.blockquote = replace(block.blockquote) - ('def', block.def) - (); - -block._tag = '(?!(?:' - + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' - + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' - + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b'; - -block.html = replace(block.html) - ('comment', /<!--[\s\S]*?-->/) - ('closed', /<(tag)[\s\S]+?<\/\1>/) - ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/) - (/tag/g, block._tag) - (); - -block.paragraph = replace(block.paragraph) - ('hr', block.hr) - ('heading', block.heading) - ('lheading', block.lheading) - ('blockquote', block.blockquote) - ('tag', '<' + block._tag) - ('def', block.def) - (); - -/** - * Normal Block Grammar - */ - -block.normal = merge({}, block); - -/** - * GFM Block Grammar - */ - -block.gfm = merge({}, block.normal, { - fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/, - paragraph: /^/, - heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ -}); - -block.gfm.paragraph = replace(block.paragraph) - ('(?!', '(?!' - + block.gfm.fences.source.replace('\\1', '\\2') + '|' - + block.list.source.replace('\\1', '\\3') + '|') - (); - -/** - * GFM + Tables Block Grammar - */ - -block.tables = merge({}, block.gfm, { - nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, - table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ -}); - -/** - * Block Lexer - */ - -function Lexer(options) { - this.tokens = []; - this.tokens.links = {}; - this.options = options || marked.defaults; - this.rules = block.normal; - - if (this.options.gfm) { - if (this.options.tables) { - this.rules = block.tables; - } else { - this.rules = block.gfm; - } - } -} - -/** - * Expose Block Rules - */ - -Lexer.rules = block; - -/** - * Static Lex Method - */ - -Lexer.lex = function(src, options) { - var lexer = new Lexer(options); - return lexer.lex(src); -}; - -/** - * Preprocessing - */ - -Lexer.prototype.lex = function(src) { - src = src - .replace(/\r\n|\r/g, '\n') - .replace(/\t/g, ' ') - .replace(/\u00a0/g, ' ') - .replace(/\u2424/g, '\n'); - - return this.token(src, true); -}; - -/** - * Lexing - */ - -Lexer.prototype.token = function(src, top, bq) { - var src = src.replace(/^ +$/gm, '') - , next - , loose - , cap - , bull - , b - , item - , space - , i - , l; - - while (src) { - // newline - if (cap = this.rules.newline.exec(src)) { - src = src.substring(cap[0].length); - if (cap[0].length > 1) { - this.tokens.push({ - type: 'space' - }); - } - } - - // code - if (cap = this.rules.code.exec(src)) { - src = src.substring(cap[0].length); - cap = cap[0].replace(/^ {4}/gm, ''); - this.tokens.push({ - type: 'code', - text: !this.options.pedantic - ? cap.replace(/\n+$/, '') - : cap - }); - continue; - } - - // fences (gfm) - if (cap = this.rules.fences.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'code', - lang: cap[2], - text: cap[3] || '' - }); - continue; - } - - // heading - if (cap = this.rules.heading.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[1].length, - text: cap[2] - }); - continue; - } - - // table no leading pipe (gfm) - if (top && (cap = this.rules.nptable.exec(src))) { - src = src.substring(cap[0].length); - - item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/\n$/, '').split('\n') - }; - - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } - - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i].split(/ *\| */); - } - - this.tokens.push(item); - - continue; - } - - // lheading - if (cap = this.rules.lheading.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[2] === '=' ? 1 : 2, - text: cap[1] - }); - continue; - } - - // hr - if (cap = this.rules.hr.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'hr' - }); - continue; - } - - // blockquote - if (cap = this.rules.blockquote.exec(src)) { - src = src.substring(cap[0].length); - - this.tokens.push({ - type: 'blockquote_start' - }); - - cap = cap[0].replace(/^ *> ?/gm, ''); - - // Pass `top` to keep the current - // "toplevel" state. This is exactly - // how markdown.pl works. - this.token(cap, top, true); - - this.tokens.push({ - type: 'blockquote_end' - }); - - continue; - } - - // list - if (cap = this.rules.list.exec(src)) { - src = src.substring(cap[0].length); - bull = cap[2]; - - this.tokens.push({ - type: 'list_start', - ordered: bull.length > 1 - }); - - // Get each top-level item. - cap = cap[0].match(this.rules.item); - - next = false; - l = cap.length; - i = 0; - - for (; i < l; i++) { - item = cap[i]; - - // Remove the list item's bullet - // so it is seen as the next token. - space = item.length; - item = item.replace(/^ *([*+-]|\d+\.) +/, ''); - - // Outdent whatever the - // list item contains. Hacky. - if (~item.indexOf('\n ')) { - space -= item.length; - item = !this.options.pedantic - ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') - : item.replace(/^ {1,4}/gm, ''); - } - - // Determine whether the next list item belongs here. - // Backpedal if it does not belong in this list. - if (this.options.smartLists && i !== l - 1) { - b = block.bullet.exec(cap[i + 1])[0]; - if (bull !== b && !(bull.length > 1 && b.length > 1)) { - src = cap.slice(i + 1).join('\n') + src; - i = l - 1; - } - } - - // Determine whether item is loose or not. - // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ - // for discount behavior. - loose = next || /\n\n(?!\s*$)/.test(item); - if (i !== l - 1) { - next = item.charAt(item.length - 1) === '\n'; - if (!loose) loose = next; - } - - this.tokens.push({ - type: loose - ? 'loose_item_start' - : 'list_item_start' - }); - - // Recurse. - this.token(item, false, bq); - - this.tokens.push({ - type: 'list_item_end' - }); - } - - this.tokens.push({ - type: 'list_end' - }); - - continue; - } - - // html - if (cap = this.rules.html.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: this.options.sanitize - ? 'paragraph' - : 'html', - pre: !this.options.sanitizer - && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), - text: cap[0] - }); - continue; - } - - // def - if ((!bq && top) && (cap = this.rules.def.exec(src))) { - src = src.substring(cap[0].length); - this.tokens.links[cap[1].toLowerCase()] = { - href: cap[2], - title: cap[3] - }; - continue; - } - - // table (gfm) - if (top && (cap = this.rules.table.exec(src))) { - src = src.substring(cap[0].length); - - item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') - }; - - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } - - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i] - .replace(/^ *\| *| *\| *$/g, '') - .split(/ *\| */); - } - - this.tokens.push(item); - - continue; - } - - // top-level paragraph - if (top && (cap = this.rules.paragraph.exec(src))) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'paragraph', - text: cap[1].charAt(cap[1].length - 1) === '\n' - ? cap[1].slice(0, -1) - : cap[1] - }); - continue; - } - - // text - if (cap = this.rules.text.exec(src)) { - // Top-level should never reach here. - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'text', - text: cap[0] - }); - continue; - } - - if (src) { - throw new - Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } - } - - return this.tokens; -}; - -/** - * Inline-Level Grammar - */ - -var inline = { - escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, - autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, - url: noop, - tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/, - link: /^!?\[(inside)\]\(href\)/, - reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, - nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, - strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, - em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, - code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, - br: /^ {2,}\n(?!\s*$)/, - del: noop, - text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/ -}; - -inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/; -inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/; - -inline.link = replace(inline.link) - ('inside', inline._inside) - ('href', inline._href) - (); - -inline.reflink = replace(inline.reflink) - ('inside', inline._inside) - (); - -/** - * Normal Inline Grammar - */ - -inline.normal = merge({}, inline); - -/** - * Pedantic Inline Grammar - */ - -inline.pedantic = merge({}, inline.normal, { - strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, - em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ -}); - -/** - * GFM Inline Grammar - */ - -inline.gfm = merge({}, inline.normal, { - escape: replace(inline.escape)('])', '~|])')(), - url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, - del: /^~~(?=\S)([\s\S]*?\S)~~/, - text: replace(inline.text) - (']|', '~]|') - ('|', '|https?://|') - () -}); - -/** - * GFM + Line Breaks Inline Grammar - */ - -inline.breaks = merge({}, inline.gfm, { - br: replace(inline.br)('{2,}', '*')(), - text: replace(inline.gfm.text)('{2,}', '*')() -}); - -/** - * Inline Lexer & Compiler - */ - -function InlineLexer(links, options) { - this.options = options || marked.defaults; - this.links = links; - this.rules = inline.normal; - this.renderer = this.options.renderer || new Renderer; - this.renderer.options = this.options; - - if (!this.links) { - throw new - Error('Tokens array requires a `links` property.'); - } - - if (this.options.gfm) { - if (this.options.breaks) { - this.rules = inline.breaks; - } else { - this.rules = inline.gfm; - } - } else if (this.options.pedantic) { - this.rules = inline.pedantic; - } -} - -/** - * Expose Inline Rules - */ - -InlineLexer.rules = inline; - -/** - * Static Lexing/Compiling Method - */ - -InlineLexer.output = function(src, links, options) { - var inline = new InlineLexer(links, options); - return inline.output(src); -}; - -/** - * Lexing/Compiling - */ - -InlineLexer.prototype.output = function(src) { - var out = '' - , link - , text - , href - , cap; - - while (src) { - // escape - if (cap = this.rules.escape.exec(src)) { - src = src.substring(cap[0].length); - out += cap[1]; - continue; - } - - // autolink - if (cap = this.rules.autolink.exec(src)) { - src = src.substring(cap[0].length); - if (cap[2] === '@') { - text = cap[1].charAt(6) === ':' - ? this.mangle(cap[1].substring(7)) - : this.mangle(cap[1]); - href = this.mangle('mailto:') + text; - } else { - text = escape(cap[1]); - href = text; - } - out += this.renderer.link(href, null, text); - continue; - } - - // url (gfm) - if (!this.inLink && (cap = this.rules.url.exec(src))) { - src = src.substring(cap[0].length); - text = escape(cap[1]); - href = text; - out += this.renderer.link(href, null, text); - continue; - } - - // tag - if (cap = this.rules.tag.exec(src)) { - if (!this.inLink && /^<a /i.test(cap[0])) { - this.inLink = true; - } else if (this.inLink && /^<\/a>/i.test(cap[0])) { - this.inLink = false; - } - src = src.substring(cap[0].length); - out += this.options.sanitize - ? this.options.sanitizer - ? this.options.sanitizer(cap[0]) - : escape(cap[0]) - : cap[0] - continue; - } - - // link - if (cap = this.rules.link.exec(src)) { - src = src.substring(cap[0].length); - this.inLink = true; - out += this.outputLink(cap, { - href: cap[2], - title: cap[3] - }); - this.inLink = false; - continue; - } - - // reflink, nolink - if ((cap = this.rules.reflink.exec(src)) - || (cap = this.rules.nolink.exec(src))) { - src = src.substring(cap[0].length); - link = (cap[2] || cap[1]).replace(/\s+/g, ' '); - link = this.links[link.toLowerCase()]; - if (!link || !link.href) { - out += cap[0].charAt(0); - src = cap[0].substring(1) + src; - continue; - } - this.inLink = true; - out += this.outputLink(cap, link); - this.inLink = false; - continue; - } - - // strong - if (cap = this.rules.strong.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.strong(this.output(cap[2] || cap[1])); - continue; - } - - // em - if (cap = this.rules.em.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.em(this.output(cap[2] || cap[1])); - continue; - } - - // code - if (cap = this.rules.code.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.codespan(escape(cap[2], true)); - continue; - } - - // br - if (cap = this.rules.br.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.br(); - continue; - } - - // del (gfm) - if (cap = this.rules.del.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.del(this.output(cap[1])); - continue; - } - - // text - if (cap = this.rules.text.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.text(escape(this.smartypants(cap[0]))); - continue; - } - - if (src) { - throw new - Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } - } - - return out; -}; - -/** - * Compile Link - */ - -InlineLexer.prototype.outputLink = function(cap, link) { - var href = escape(link.href) - , title = link.title ? escape(link.title) : null; - - return cap[0].charAt(0) !== '!' - ? this.renderer.link(href, title, this.output(cap[1])) - : this.renderer.image(href, title, escape(cap[1])); -}; - -/** - * Smartypants Transformations - */ - -InlineLexer.prototype.smartypants = function(text) { - if (!this.options.smartypants) return text; - return text - // em-dashes - .replace(/---/g, '\u2014') - // en-dashes - .replace(/--/g, '\u2013') - // opening singles - .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') - // closing singles & apostrophes - .replace(/'/g, '\u2019') - // opening doubles - .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') - // closing doubles - .replace(/"/g, '\u201d') - // ellipses - .replace(/\.{3}/g, '\u2026'); -}; - -/** - * Mangle Links - */ - -InlineLexer.prototype.mangle = function(text) { - if (!this.options.mangle) return text; - var out = '' - , l = text.length - , i = 0 - , ch; - - for (; i < l; i++) { - ch = text.charCodeAt(i); - if (Math.random() > 0.5) { - ch = 'x' + ch.toString(16); - } - out += '&#' + ch + ';'; - } - - return out; -}; - -/** - * Renderer - */ - -function Renderer(options) { - this.options = options || {}; -} - -Renderer.prototype.code = function(code, lang, escaped) { - if (this.options.highlight) { - var out = this.options.highlight(code, lang); - if (out != null && out !== code) { - escaped = true; - code = out; - } - } - - if (!lang) { - return '<pre><code>' - + (escaped ? code : escape(code, true)) - + '\n</code></pre>'; - } - - return '<pre><code class="' - + this.options.langPrefix - + escape(lang, true) - + '">' - + (escaped ? code : escape(code, true)) - + '\n</code></pre>\n'; -}; - -Renderer.prototype.blockquote = function(quote) { - return '<blockquote>\n' + quote + '</blockquote>\n'; -}; - -Renderer.prototype.html = function(html) { - return html; -}; - -Renderer.prototype.heading = function(text, level, raw) { - return '<h' - + level - + ' id="' - + this.options.headerPrefix - + raw.toLowerCase().replace(/[^\w]+/g, '-') - + '">' - + text - + '</h' - + level - + '>\n'; -}; - -Renderer.prototype.hr = function() { - return this.options.xhtml ? '<hr/>\n' : '<hr>\n'; -}; - -Renderer.prototype.list = function(body, ordered) { - var type = ordered ? 'ol' : 'ul'; - return '<' + type + '>\n' + body + '</' + type + '>\n'; -}; - -Renderer.prototype.listitem = function(text) { - return '<li>' + text + '</li>\n'; -}; - -Renderer.prototype.paragraph = function(text) { - return '<p>' + text + '</p>\n'; -}; - -Renderer.prototype.table = function(header, body) { - return '<table>\n' - + '<thead>\n' - + header - + '</thead>\n' - + '<tbody>\n' - + body - + '</tbody>\n' - + '</table>\n'; -}; - -Renderer.prototype.tablerow = function(content) { - return '<tr>\n' + content + '</tr>\n'; -}; - -Renderer.prototype.tablecell = function(content, flags) { - var type = flags.header ? 'th' : 'td'; - var tag = flags.align - ? '<' + type + ' style="text-align:' + flags.align + '">' - : '<' + type + '>'; - return tag + content + '</' + type + '>\n'; -}; - -// span level renderer -Renderer.prototype.strong = function(text) { - return '<strong>' + text + '</strong>'; -}; - -Renderer.prototype.em = function(text) { - return '<em>' + text + '</em>'; -}; - -Renderer.prototype.codespan = function(text) { - return '<code>' + text + '</code>'; -}; - -Renderer.prototype.br = function() { - return this.options.xhtml ? '<br/>' : '<br>'; -}; - -Renderer.prototype.del = function(text) { - return '<del>' + text + '</del>'; -}; - -Renderer.prototype.link = function(href, title, text) { - if (this.options.sanitize) { - try { - var prot = decodeURIComponent(unescape(href)) - .replace(/[^\w:]/g, '') - .toLowerCase(); - } catch (e) { - return ''; - } - if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) { - return ''; - } - } - var out = '<a href="' + href + '"'; - if (title) { - out += ' title="' + title + '"'; - } - out += '>' + text + '</a>'; - return out; -}; - -Renderer.prototype.image = function(href, title, text) { - var out = '<img src="' + href + '" alt="' + text + '"'; - if (title) { - out += ' title="' + title + '"'; - } - out += this.options.xhtml ? '/>' : '>'; - return out; -}; - -Renderer.prototype.text = function(text) { - return text; -}; - -/** - * Parsing & Compiling - */ - -function Parser(options) { - this.tokens = []; - this.token = null; - this.options = options || marked.defaults; - this.options.renderer = this.options.renderer || new Renderer; - this.renderer = this.options.renderer; - this.renderer.options = this.options; -} - -/** - * Static Parse Method - */ - -Parser.parse = function(src, options, renderer) { - var parser = new Parser(options, renderer); - return parser.parse(src); -}; - -/** - * Parse Loop - */ - -Parser.prototype.parse = function(src) { - this.inline = new InlineLexer(src.links, this.options, this.renderer); - this.tokens = src.reverse(); - - var out = ''; - while (this.next()) { - out += this.tok(); - } - - return out; -}; - -/** - * Next Token - */ - -Parser.prototype.next = function() { - return this.token = this.tokens.pop(); -}; - -/** - * Preview Next Token - */ - -Parser.prototype.peek = function() { - return this.tokens[this.tokens.length - 1] || 0; -}; - -/** - * Parse Text Tokens - */ - -Parser.prototype.parseText = function() { - var body = this.token.text; - - while (this.peek().type === 'text') { - body += '\n' + this.next().text; - } - - return this.inline.output(body); -}; - -/** - * Parse Current Token - */ - -Parser.prototype.tok = function() { - switch (this.token.type) { - case 'space': { - return ''; - } - case 'hr': { - return this.renderer.hr(); - } - case 'heading': { - return this.renderer.heading( - this.inline.output(this.token.text), - this.token.depth, - this.token.text); - } - case 'code': { - return this.renderer.code(this.token.text, - this.token.lang, - this.token.escaped); - } - case 'table': { - var header = '' - , body = '' - , i - , row - , cell - , flags - , j; - - // header - cell = ''; - for (i = 0; i < this.token.header.length; i++) { - flags = { header: true, align: this.token.align[i] }; - cell += this.renderer.tablecell( - this.inline.output(this.token.header[i]), - { header: true, align: this.token.align[i] } - ); - } - header += this.renderer.tablerow(cell); - - for (i = 0; i < this.token.cells.length; i++) { - row = this.token.cells[i]; - - cell = ''; - for (j = 0; j < row.length; j++) { - cell += this.renderer.tablecell( - this.inline.output(row[j]), - { header: false, align: this.token.align[j] } - ); - } - - body += this.renderer.tablerow(cell); - } - return this.renderer.table(header, body); - } - case 'blockquote_start': { - var body = ''; - - while (this.next().type !== 'blockquote_end') { - body += this.tok(); - } - - return this.renderer.blockquote(body); - } - case 'list_start': { - var body = '' - , ordered = this.token.ordered; - - while (this.next().type !== 'list_end') { - body += this.tok(); - } - - return this.renderer.list(body, ordered); - } - case 'list_item_start': { - var body = ''; - - while (this.next().type !== 'list_item_end') { - body += this.token.type === 'text' - ? this.parseText() - : this.tok(); - } - - return this.renderer.listitem(body); - } - case 'loose_item_start': { - var body = ''; - - while (this.next().type !== 'list_item_end') { - body += this.tok(); - } - - return this.renderer.listitem(body); - } - case 'html': { - var html = !this.token.pre && !this.options.pedantic - ? this.inline.output(this.token.text) - : this.token.text; - return this.renderer.html(html); - } - case 'paragraph': { - return this.renderer.paragraph(this.inline.output(this.token.text)); - } - case 'text': { - return this.renderer.paragraph(this.parseText()); - } - } -}; - -/** - * Helpers - */ - -function escape(html, encode) { - return html - .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} - -function unescape(html) { - // explicitly match decimal, hex, and named HTML entities - return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) { - n = n.toLowerCase(); - if (n === 'colon') return ':'; - if (n.charAt(0) === '#') { - return n.charAt(1) === 'x' - ? String.fromCharCode(parseInt(n.substring(2), 16)) - : String.fromCharCode(+n.substring(1)); - } - return ''; - }); -} - -function replace(regex, opt) { - regex = regex.source; - opt = opt || ''; - return function self(name, val) { - if (!name) return new RegExp(regex, opt); - val = val.source || val; - val = val.replace(/(^|[^\[])\^/g, '$1'); - regex = regex.replace(name, val); - return self; - }; -} - -function noop() {} -noop.exec = noop; - -function merge(obj) { - var i = 1 - , target - , key; - - for (; i < arguments.length; i++) { - target = arguments[i]; - for (key in target) { - if (Object.prototype.hasOwnProperty.call(target, key)) { - obj[key] = target[key]; - } - } - } - - return obj; -} - - -/** - * Marked - */ - -function marked(src, opt, callback) { - if (callback || typeof opt === 'function') { - if (!callback) { - callback = opt; - opt = null; - } - - opt = merge({}, marked.defaults, opt || {}); - - var highlight = opt.highlight - , tokens - , pending - , i = 0; - - try { - tokens = Lexer.lex(src, opt) - } catch (e) { - return callback(e); - } - - pending = tokens.length; - - var done = function(err) { - if (err) { - opt.highlight = highlight; - return callback(err); - } - - var out; - - try { - out = Parser.parse(tokens, opt); - } catch (e) { - err = e; - } - - opt.highlight = highlight; - - return err - ? callback(err) - : callback(null, out); - }; - - if (!highlight || highlight.length < 3) { - return done(); - } - - delete opt.highlight; - - if (!pending) return done(); - - for (; i < tokens.length; i++) { - (function(token) { - if (token.type !== 'code') { - return --pending || done(); - } - return highlight(token.text, token.lang, function(err, code) { - if (err) return done(err); - if (code == null || code === token.text) { - return --pending || done(); - } - token.text = code; - token.escaped = true; - --pending || done(); - }); - })(tokens[i]); - } - - return; - } - try { - if (opt) opt = merge({}, marked.defaults, opt); - return Parser.parse(Lexer.lex(src, opt), opt); - } catch (e) { - e.message += '\nPlease report this to https://github.com/chjj/marked.'; - if ((opt || marked.defaults).silent) { - return '<p>An error occured:</p><pre>' - + escape(e.message + '', true) - + '</pre>'; - } - throw e; - } -} - -/** - * Options - */ - -marked.options = -marked.setOptions = function(opt) { - merge(marked.defaults, opt); - return marked; -}; - -marked.defaults = { - gfm: true, - tables: true, - breaks: false, - pedantic: false, - sanitize: false, - sanitizer: null, - mangle: true, - smartLists: false, - silent: false, - highlight: null, - langPrefix: 'lang-', - smartypants: false, - headerPrefix: '', - renderer: new Renderer, - xhtml: false -}; - -/** - * Expose - */ - -marked.Parser = Parser; -marked.parser = Parser.parse; - -marked.Renderer = Renderer; - -marked.Lexer = Lexer; -marked.lexer = Lexer.lex; - -marked.InlineLexer = InlineLexer; -marked.inlineLexer = InlineLexer.output; - -marked.parse = marked; - -if (true) { - module.exports = marked; -} else if (typeof define === 'function' && define.amd) { - define(function() { return marked; }); -} else { - this.marked = marked; -} - -}).call(function() { - return this || (typeof window !== 'undefined' ? window : global); -}()); - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4))) - -/***/ }), -/* 26 */ -/***/ (function(module, exports) { - -Prism.languages.python= { - 'triple-quoted-string': { - pattern: /"""[\s\S]+?"""|'''[\s\S]+?'''/, - alias: 'string' - }, - 'comment': { - pattern: /(^|[^\\])#.*/, - lookbehind: true - }, - 'string': { - pattern: /("|')(?:\\\\|\\?[^\\\r\n])*?\1/, - greedy: true - }, - 'function' : { - pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_][a-zA-Z0-9_]*(?=\()/g, - lookbehind: true - }, - 'class-name': { - pattern: /(\bclass\s+)[a-z0-9_]+/i, - lookbehind: true - }, - 'keyword' : /\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/, - 'boolean' : /\b(?:True|False)\b/, - 'number' : /\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i, - 'operator' : /[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/, - 'punctuation' : /[{}[\];(),.:]/ -}; - - -/***/ }), -/* 27 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global) {(function(){ - -if ( - (typeof self === 'undefined' || !self.Prism) && - (typeof global === 'undefined' || !global.Prism) -) { - return; -} - -var options = {}; -Prism.plugins.customClass = { - map: function map(cm) { - options.classMap = cm; - }, - prefix: function prefix(string) { - options.prefixString = string; - } -} - -Prism.hooks.add('wrap', function (env) { - if (!options.classMap && !options.prefixString) { - return; - } - env.classes = env.classes.map(function(c) { - return (options.prefixString || '') + (options.classMap[c] || c); - }); -}); - -})(); - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4))) - -/***/ }), -/* 28 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global) { -/* ********************************************** - Begin prism-core.js -********************************************** */ - -var _self = (typeof window !== 'undefined') - ? window // if in browser - : ( - (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) - ? self // if in worker - : {} // if in node js - ); - -/** - * Prism: Lightweight, robust, elegant syntax highlighting - * MIT license http://www.opensource.org/licenses/mit-license.php/ - * @author Lea Verou http://lea.verou.me - */ - -var Prism = (function(){ - -// Private helper vars -var lang = /\blang(?:uage)?-(\w+)\b/i; -var uniqueId = 0; - -var _ = _self.Prism = { - util: { - encode: function (tokens) { - if (tokens instanceof Token) { - return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias); - } else if (_.util.type(tokens) === 'Array') { - return tokens.map(_.util.encode); - } else { - return tokens.replace(/&/g, '&').replace(/</g, '<').replace(/\u00a0/g, ' '); - } - }, - - type: function (o) { - return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1]; - }, - - objId: function (obj) { - if (!obj['__id']) { - Object.defineProperty(obj, '__id', { value: ++uniqueId }); - } - return obj['__id']; - }, - - // Deep clone a language definition (e.g. to extend it) - clone: function (o) { - var type = _.util.type(o); - - switch (type) { - case 'Object': - var clone = {}; - - for (var key in o) { - if (o.hasOwnProperty(key)) { - clone[key] = _.util.clone(o[key]); - } - } - - return clone; - - case 'Array': - // Check for existence for IE8 - return o.map && o.map(function(v) { return _.util.clone(v); }); - } - - return o; - } - }, - - languages: { - extend: function (id, redef) { - var lang = _.util.clone(_.languages[id]); - - for (var key in redef) { - lang[key] = redef[key]; - } - - return lang; - }, - - /** - * Insert a token before another token in a language literal - * As this needs to recreate the object (we cannot actually insert before keys in object literals), - * we cannot just provide an object, we need anobject and a key. - * @param inside The key (or language id) of the parent - * @param before The key to insert before. If not provided, the function appends instead. - * @param insert Object with the key/value pairs to insert - * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted. - */ - insertBefore: function (inside, before, insert, root) { - root = root || _.languages; - var grammar = root[inside]; - - if (arguments.length == 2) { - insert = arguments[1]; - - for (var newToken in insert) { - if (insert.hasOwnProperty(newToken)) { - grammar[newToken] = insert[newToken]; - } - } - - return grammar; - } - - var ret = {}; - - for (var token in grammar) { - - if (grammar.hasOwnProperty(token)) { - - if (token == before) { - - for (var newToken in insert) { - - if (insert.hasOwnProperty(newToken)) { - ret[newToken] = insert[newToken]; - } - } - } - - ret[token] = grammar[token]; - } - } - - // Update references in other language definitions - _.languages.DFS(_.languages, function(key, value) { - if (value === root[inside] && key != inside) { - this[key] = ret; - } - }); - - return root[inside] = ret; - }, - - // Traverse a language definition with Depth First Search - DFS: function(o, callback, type, visited) { - visited = visited || {}; - for (var i in o) { - if (o.hasOwnProperty(i)) { - callback.call(o, i, o[i], type || i); - - if (_.util.type(o[i]) === 'Object' && !visited[_.util.objId(o[i])]) { - visited[_.util.objId(o[i])] = true; - _.languages.DFS(o[i], callback, null, visited); - } - else if (_.util.type(o[i]) === 'Array' && !visited[_.util.objId(o[i])]) { - visited[_.util.objId(o[i])] = true; - _.languages.DFS(o[i], callback, i, visited); - } - } - } - } - }, - plugins: {}, - - highlightAll: function(async, callback) { - var env = { - callback: callback, - selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code' - }; - - _.hooks.run("before-highlightall", env); - - var elements = env.elements || document.querySelectorAll(env.selector); - - for (var i=0, element; element = elements[i++];) { - _.highlightElement(element, async === true, env.callback); - } - }, - - highlightElement: function(element, async, callback) { - // Find language - var language, grammar, parent = element; - - while (parent && !lang.test(parent.className)) { - parent = parent.parentNode; - } - - if (parent) { - language = (parent.className.match(lang) || [,''])[1].toLowerCase(); - grammar = _.languages[language]; - } - - // Set language on the element, if not present - element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; - - // Set language on the parent, for styling - parent = element.parentNode; - - if (/pre/i.test(parent.nodeName)) { - parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; - } - - var code = element.textContent; - - var env = { - element: element, - language: language, - grammar: grammar, - code: code - }; - - _.hooks.run('before-sanity-check', env); - - if (!env.code || !env.grammar) { - if (env.code) { - env.element.textContent = env.code; - } - _.hooks.run('complete', env); - return; - } - - _.hooks.run('before-highlight', env); - - if (async && _self.Worker) { - var worker = new Worker(_.filename); - - worker.onmessage = function(evt) { - env.highlightedCode = evt.data; - - _.hooks.run('before-insert', env); - - env.element.innerHTML = env.highlightedCode; - - callback && callback.call(env.element); - _.hooks.run('after-highlight', env); - _.hooks.run('complete', env); - }; - - worker.postMessage(JSON.stringify({ - language: env.language, - code: env.code, - immediateClose: true - })); - } - else { - env.highlightedCode = _.highlight(env.code, env.grammar, env.language); - - _.hooks.run('before-insert', env); - - env.element.innerHTML = env.highlightedCode; - - callback && callback.call(element); - - _.hooks.run('after-highlight', env); - _.hooks.run('complete', env); - } - }, - - highlight: function (text, grammar, language) { - var tokens = _.tokenize(text, grammar); - return Token.stringify(_.util.encode(tokens), language); - }, - - tokenize: function(text, grammar, language) { - var Token = _.Token; - - var strarr = [text]; - - var rest = grammar.rest; - - if (rest) { - for (var token in rest) { - grammar[token] = rest[token]; - } - - delete grammar.rest; - } - - tokenloop: for (var token in grammar) { - if(!grammar.hasOwnProperty(token) || !grammar[token]) { - continue; - } - - var patterns = grammar[token]; - patterns = (_.util.type(patterns) === "Array") ? patterns : [patterns]; - - for (var j = 0; j < patterns.length; ++j) { - var pattern = patterns[j], - inside = pattern.inside, - lookbehind = !!pattern.lookbehind, - greedy = !!pattern.greedy, - lookbehindLength = 0, - alias = pattern.alias; - - if (greedy && !pattern.pattern.global) { - // Without the global flag, lastIndex won't work - var flags = pattern.pattern.toString().match(/[imuy]*$/)[0]; - pattern.pattern = RegExp(pattern.pattern.source, flags + "g"); - } - - pattern = pattern.pattern || pattern; - - // Don’t cache length as it changes during the loop - for (var i=0, pos = 0; i<strarr.length; pos += strarr[i].length, ++i) { - - var str = strarr[i]; - - if (strarr.length > text.length) { - // Something went terribly wrong, ABORT, ABORT! - break tokenloop; - } - - if (str instanceof Token) { - continue; - } - - pattern.lastIndex = 0; - - var match = pattern.exec(str), - delNum = 1; - - // Greedy patterns can override/remove up to two previously matched tokens - if (!match && greedy && i != strarr.length - 1) { - pattern.lastIndex = pos; - match = pattern.exec(text); - if (!match) { - break; - } - - var from = match.index + (lookbehind ? match[1].length : 0), - to = match.index + match[0].length, - k = i, - p = pos; - - for (var len = strarr.length; k < len && p < to; ++k) { - p += strarr[k].length; - // Move the index i to the element in strarr that is closest to from - if (from >= p) { - ++i; - pos = p; - } - } - - /* - * If strarr[i] is a Token, then the match starts inside another Token, which is invalid - * If strarr[k - 1] is greedy we are in conflict with another greedy pattern - */ - if (strarr[i] instanceof Token || strarr[k - 1].greedy) { - continue; - } - - // Number of tokens to delete and replace with the new match - delNum = k - i; - str = text.slice(pos, p); - match.index -= pos; - } - - if (!match) { - continue; - } - - if(lookbehind) { - lookbehindLength = match[1].length; - } - - var from = match.index + lookbehindLength, - match = match[0].slice(lookbehindLength), - to = from + match.length, - before = str.slice(0, from), - after = str.slice(to); - - var args = [i, delNum]; - - if (before) { - args.push(before); - } - - var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias, match, greedy); - - args.push(wrapped); - - if (after) { - args.push(after); - } - - Array.prototype.splice.apply(strarr, args); - } - } - } - - return strarr; - }, - - hooks: { - all: {}, - - add: function (name, callback) { - var hooks = _.hooks.all; - - hooks[name] = hooks[name] || []; - - hooks[name].push(callback); - }, - - run: function (name, env) { - var callbacks = _.hooks.all[name]; - - if (!callbacks || !callbacks.length) { - return; - } - - for (var i=0, callback; callback = callbacks[i++];) { - callback(env); - } - } - } -}; - -var Token = _.Token = function(type, content, alias, matchedStr, greedy) { - this.type = type; - this.content = content; - this.alias = alias; - // Copy of the full string this token was created from - this.length = (matchedStr || "").length|0; - this.greedy = !!greedy; -}; - -Token.stringify = function(o, language, parent) { - if (typeof o == 'string') { - return o; - } - - if (_.util.type(o) === 'Array') { - return o.map(function(element) { - return Token.stringify(element, language, o); - }).join(''); - } - - var env = { - type: o.type, - content: Token.stringify(o.content, language, parent), - tag: 'span', - classes: ['token', o.type], - attributes: {}, - language: language, - parent: parent - }; - - if (env.type == 'comment') { - env.attributes['spellcheck'] = 'true'; - } - - if (o.alias) { - var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias]; - Array.prototype.push.apply(env.classes, aliases); - } - - _.hooks.run('wrap', env); - - var attributes = Object.keys(env.attributes).map(function(name) { - return name + '="' + (env.attributes[name] || '').replace(/"/g, '"') + '"'; - }).join(' '); - - return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + '>' + env.content + '</' + env.tag + '>'; - -}; - -if (!_self.document) { - if (!_self.addEventListener) { - // in Node.js - return _self.Prism; - } - // In worker - _self.addEventListener('message', function(evt) { - var message = JSON.parse(evt.data), - lang = message.language, - code = message.code, - immediateClose = message.immediateClose; - - _self.postMessage(_.highlight(code, _.languages[lang], lang)); - if (immediateClose) { - _self.close(); - } - }, false); - - return _self.Prism; -} - -//Get current script and highlight -var script = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop(); - -if (script) { - _.filename = script.src; - - if (document.addEventListener && !script.hasAttribute('data-manual')) { - if(document.readyState !== "loading") { - if (window.requestAnimationFrame) { - window.requestAnimationFrame(_.highlightAll); - } else { - window.setTimeout(_.highlightAll, 16); - } - } - else { - document.addEventListener('DOMContentLoaded', _.highlightAll); - } - } -} - -return _self.Prism; - -})(); - -if (typeof module !== 'undefined' && module.exports) { - module.exports = Prism; -} - -// hack for components to work correctly in node.js -if (typeof global !== 'undefined') { - global.Prism = Prism; -} - - -/* ********************************************** - Begin prism-markup.js -********************************************** */ - -Prism.languages.markup = { - 'comment': /<!--[\w\W]*?-->/, - 'prolog': /<\?[\w\W]+?\?>/, - 'doctype': /<!DOCTYPE[\w\W]+?>/i, - 'cdata': /<!\[CDATA\[[\w\W]*?]]>/i, - 'tag': { - pattern: /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i, - inside: { - 'tag': { - pattern: /^<\/?[^\s>\/]+/i, - inside: { - 'punctuation': /^<\/?/, - 'namespace': /^[^\s>\/:]+:/ - } - }, - 'attr-value': { - pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i, - inside: { - 'punctuation': /[=>"']/ - } - }, - 'punctuation': /\/?>/, - 'attr-name': { - pattern: /[^\s>\/]+/, - inside: { - 'namespace': /^[^\s>\/:]+:/ - } - } - - } - }, - 'entity': /&#?[\da-z]{1,8};/i -}; - -// Plugin to make entity title show the real entity, idea by Roman Komarov -Prism.hooks.add('wrap', function(env) { - - if (env.type === 'entity') { - env.attributes['title'] = env.content.replace(/&/, '&'); - } -}); - -Prism.languages.xml = Prism.languages.markup; -Prism.languages.html = Prism.languages.markup; -Prism.languages.mathml = Prism.languages.markup; -Prism.languages.svg = Prism.languages.markup; - - -/* ********************************************** - Begin prism-css.js -********************************************** */ - -Prism.languages.css = { - 'comment': /\/\*[\w\W]*?\*\//, - 'atrule': { - pattern: /@[\w-]+?.*?(;|(?=\s*\{))/i, - inside: { - 'rule': /@[\w-]+/ - // See rest below - } - }, - 'url': /url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i, - 'selector': /[^\{\}\s][^\{\};]*?(?=\s*\{)/, - 'string': { - pattern: /("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/, - greedy: true - }, - 'property': /(\b|\B)[\w-]+(?=\s*:)/i, - 'important': /\B!important\b/i, - 'function': /[-a-z0-9]+(?=\()/i, - 'punctuation': /[(){};:]/ -}; - -Prism.languages.css['atrule'].inside.rest = Prism.util.clone(Prism.languages.css); - -if (Prism.languages.markup) { - Prism.languages.insertBefore('markup', 'tag', { - 'style': { - pattern: /(<style[\w\W]*?>)[\w\W]*?(?=<\/style>)/i, - lookbehind: true, - inside: Prism.languages.css, - alias: 'language-css' - } - }); - - Prism.languages.insertBefore('inside', 'attr-value', { - 'style-attr': { - pattern: /\s*style=("|').*?\1/i, - inside: { - 'attr-name': { - pattern: /^\s*style/i, - inside: Prism.languages.markup.tag.inside - }, - 'punctuation': /^\s*=\s*['"]|['"]\s*$/, - 'attr-value': { - pattern: /.+/i, - inside: Prism.languages.css - } - }, - alias: 'language-css' - } - }, Prism.languages.markup.tag); -} - -/* ********************************************** - Begin prism-clike.js -********************************************** */ - -Prism.languages.clike = { - 'comment': [ - { - pattern: /(^|[^\\])\/\*[\w\W]*?\*\//, - lookbehind: true - }, - { - pattern: /(^|[^\\:])\/\/.*/, - lookbehind: true - } - ], - 'string': { - pattern: /(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, - greedy: true - }, - 'class-name': { - pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i, - lookbehind: true, - inside: { - punctuation: /(\.|\\)/ - } - }, - 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/, - 'boolean': /\b(true|false)\b/, - 'function': /[a-z0-9_]+(?=\()/i, - 'number': /\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i, - 'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/, - 'punctuation': /[{}[\];(),.:]/ -}; - - -/* ********************************************** - Begin prism-javascript.js -********************************************** */ - -Prism.languages.javascript = Prism.languages.extend('clike', { - 'keyword': /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/, - 'number': /\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/, - // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444) - 'function': /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i, - 'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*\*?|\/|~|\^|%|\.{3}/ -}); - -Prism.languages.insertBefore('javascript', 'keyword', { - 'regex': { - pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/, - lookbehind: true, - greedy: true - } -}); - -Prism.languages.insertBefore('javascript', 'string', { - 'template-string': { - pattern: /`(?:\\\\|\\?[^\\])*?`/, - greedy: true, - inside: { - 'interpolation': { - pattern: /\$\{[^}]+\}/, - inside: { - 'interpolation-punctuation': { - pattern: /^\$\{|\}$/, - alias: 'punctuation' - }, - rest: Prism.languages.javascript - } - }, - 'string': /[\s\S]+/ - } - } -}); - -if (Prism.languages.markup) { - Prism.languages.insertBefore('markup', 'tag', { - 'script': { - pattern: /(<script[\w\W]*?>)[\w\W]*?(?=<\/script>)/i, - lookbehind: true, - inside: Prism.languages.javascript, - alias: 'language-javascript' - } - }); -} - -Prism.languages.js = Prism.languages.javascript; - -/* ********************************************** - Begin prism-file-highlight.js -********************************************** */ - -(function () { - if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) { - return; - } - - self.Prism.fileHighlight = function() { - - var Extensions = { - 'js': 'javascript', - 'py': 'python', - 'rb': 'ruby', - 'ps1': 'powershell', - 'psm1': 'powershell', - 'sh': 'bash', - 'bat': 'batch', - 'h': 'c', - 'tex': 'latex' - }; - - if(Array.prototype.forEach) { // Check to prevent error in IE8 - Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function (pre) { - var src = pre.getAttribute('data-src'); - - var language, parent = pre; - var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i; - while (parent && !lang.test(parent.className)) { - parent = parent.parentNode; - } - - if (parent) { - language = (pre.className.match(lang) || [, ''])[1]; - } - - if (!language) { - var extension = (src.match(/\.(\w+)$/) || [, ''])[1]; - language = Extensions[extension] || extension; - } - - var code = document.createElement('code'); - code.className = 'language-' + language; - - pre.textContent = ''; - - code.textContent = 'Loading…'; - - pre.appendChild(code); - - var xhr = new XMLHttpRequest(); - - xhr.open('GET', src, true); - - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - - if (xhr.status < 400 && xhr.responseText) { - code.textContent = xhr.responseText; - - Prism.highlightElement(code); - } - else if (xhr.status >= 400) { - code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText; - } - else { - code.textContent = '✖ Error: File does not exist or is empty'; - } - } - }; - - xhr.send(null); - }); - } - - }; - - document.addEventListener('DOMContentLoaded', self.Prism.fileHighlight); - -})(); - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4))) - -/***/ }), -/* 29 */ -/***/ (function(module, exports, __webpack_require__) { - - -/* styles */ -__webpack_require__(42) - -var Component = __webpack_require__(0)( - /* script */ - __webpack_require__(7), - /* template */ - __webpack_require__(36), - /* scopeId */ - "data-v-3ac4c361", - /* cssModules */ - null -) - -module.exports = Component.exports - - -/***/ }), -/* 30 */ -/***/ (function(module, exports, __webpack_require__) { - - -/* styles */ -__webpack_require__(45) - -var Component = __webpack_require__(0)( - /* script */ - __webpack_require__(9), - /* template */ - __webpack_require__(40), - /* scopeId */ - null, - /* cssModules */ - null -) - -module.exports = Component.exports - - -/***/ }), -/* 31 */ -/***/ (function(module, exports, __webpack_require__) { - -var Component = __webpack_require__(0)( - /* script */ - __webpack_require__(10), - /* template */ - __webpack_require__(37), - /* scopeId */ - null, - /* cssModules */ - null -) - -module.exports = Component.exports - - -/***/ }), -/* 32 */ -/***/ (function(module, exports, __webpack_require__) { - -var Component = __webpack_require__(0)( - /* script */ - __webpack_require__(11), - /* template */ - __webpack_require__(34), - /* scopeId */ - null, - /* cssModules */ - null -) - -module.exports = Component.exports - - -/***/ }), -/* 33 */ -/***/ (function(module, exports, __webpack_require__) { - -var Component = __webpack_require__(0)( - /* script */ - __webpack_require__(12), - /* template */ - __webpack_require__(35), - /* scopeId */ - null, - /* cssModules */ - null -) - -module.exports = Component.exports - - -/***/ }), -/* 34 */ -/***/ (function(module, exports) { - -module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h; - return _c('div', { - staticClass: "output" - }, [_c('prompt'), _vm._v(" "), _c('img', { - attrs: { - "src": 'data:' + _vm.outputType + ';base64,' + _vm.rawCode - } - })], 1) -},staticRenderFns: []} - -/***/ }), -/* 35 */ -/***/ (function(module, exports) { - -module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h; - return _c(_vm.componentName, { - tag: "component", - attrs: { - "type": "output", - "outputType": _vm.outputType, - "count": _vm.count, - "raw-code": _vm.rawCode, - "code-css-class": _vm.codeCssClass - } - }) -},staticRenderFns: []} - -/***/ }), -/* 36 */ -/***/ (function(module, exports) { - -module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h; - return _c('div', { - staticClass: "cell" - }, [_c('code-cell', { - attrs: { - "type": "input", - "raw-code": _vm.rawInputCode, - "count": _vm.cell.execution_count, - "code-css-class": _vm.codeCssClass - } - }), _vm._v(" "), (_vm.hasOutput) ? _c('output-cell', { - attrs: { - "count": _vm.cell.execution_count, - "output": _vm.output, - "code-css-class": _vm.codeCssClass - } - }) : _vm._e()], 1) -},staticRenderFns: []} - -/***/ }), -/* 37 */ -/***/ (function(module, exports) { - -module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h; - return _c('div', { - staticClass: "output" - }, [_c('prompt'), _vm._v(" "), _c('div', { - domProps: { - "innerHTML": _vm._s(_vm.rawCode) - } - })], 1) -},staticRenderFns: []} - -/***/ }), -/* 38 */ -/***/ (function(module, exports) { - -module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h; - return (_vm.hasNotebook) ? _c('div', _vm._l((_vm.cells), function(cell, index) { - return _c(_vm.cellType(cell.cell_type), { - key: index, - tag: "component", - attrs: { - "cell": cell, - "code-css-class": _vm.codeCssClass - } - }) - })) : _vm._e() -},staticRenderFns: []} - -/***/ }), -/* 39 */ -/***/ (function(module, exports) { - -module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h; - return _c('div', { - staticClass: "prompt" - }, [(_vm.type && _vm.count) ? _c('span', [_vm._v("\n " + _vm._s(_vm.type) + " [" + _vm._s(_vm.count) + "]:\n ")]) : _vm._e()]) -},staticRenderFns: []} - -/***/ }), -/* 40 */ -/***/ (function(module, exports) { - -module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h; - return _c('div', { - staticClass: "cell text-cell" - }, [_c('prompt'), _vm._v(" "), _c('div', { - staticClass: "markdown", - domProps: { - "innerHTML": _vm._s(_vm.markdown) - } - })], 1) -},staticRenderFns: []} - -/***/ }), -/* 41 */ -/***/ (function(module, exports) { - -module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h; - return _c('div', { - class: _vm.type - }, [_c('prompt', { - attrs: { - "type": _vm.promptType, - "count": _vm.count - } - }), _vm._v(" "), _c('pre', { - ref: "code", - staticClass: "language-python", - class: _vm.codeCssClass, - domProps: { - "textContent": _vm._s(_vm.code) - } - }, [_vm._v("\n ")])], 1) -},staticRenderFns: []} - -/***/ }), -/* 42 */ -/***/ (function(module, exports, __webpack_require__) { - -// style-loader: Adds some css to the DOM by adding a <style> tag - -// load the styles -var content = __webpack_require__(19); -if(typeof content === 'string') content = [[module.i, content, '']]; -if(content.locals) module.exports = content.locals; -// add the styles to the DOM -var update = __webpack_require__(3)("74a276de", content, true); -// Hot Module Replacement -if(false) { - // When the styles change, update the <style> tags - if(!content.locals) { - module.hot.accept("!!../../node_modules/css-loader/index.js?minimize!../../node_modules/vue-loader/lib/style-compiler/index.js?{\"id\":\"data-v-3ac4c361\",\"scoped\":true,\"hasInlineConfig\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./code.vue", function() { - var newContent = require("!!../../node_modules/css-loader/index.js?minimize!../../node_modules/vue-loader/lib/style-compiler/index.js?{\"id\":\"data-v-3ac4c361\",\"scoped\":true,\"hasInlineConfig\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./code.vue"); - if(typeof newContent === 'string') newContent = [[module.id, newContent, '']]; - update(newContent); - }); - } - // When the module is disposed, remove the <style> tags - module.hot.dispose(function() { update(); }); -} - -/***/ }), -/* 43 */ -/***/ (function(module, exports, __webpack_require__) { - -// style-loader: Adds some css to the DOM by adding a <style> tag - -// load the styles -var content = __webpack_require__(20); -if(typeof content === 'string') content = [[module.i, content, '']]; -if(content.locals) module.exports = content.locals; -// add the styles to the DOM -var update = __webpack_require__(3)("55f9d67b", content, true); -// Hot Module Replacement -if(false) { - // When the styles change, update the <style> tags - if(!content.locals) { - module.hot.accept("!!../node_modules/css-loader/index.js?minimize!../node_modules/vue-loader/lib/style-compiler/index.js?{\"id\":\"data-v-4cb2b168\",\"scoped\":false,\"hasInlineConfig\":false}!../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./index.vue", function() { - var newContent = require("!!../node_modules/css-loader/index.js?minimize!../node_modules/vue-loader/lib/style-compiler/index.js?{\"id\":\"data-v-4cb2b168\",\"scoped\":false,\"hasInlineConfig\":false}!../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./index.vue"); - if(typeof newContent === 'string') newContent = [[module.id, newContent, '']]; - update(newContent); - }); - } - // When the module is disposed, remove the <style> tags - module.hot.dispose(function() { update(); }); -} - -/***/ }), -/* 44 */ -/***/ (function(module, exports, __webpack_require__) { - -// style-loader: Adds some css to the DOM by adding a <style> tag - -// load the styles -var content = __webpack_require__(21); -if(typeof content === 'string') content = [[module.i, content, '']]; -if(content.locals) module.exports = content.locals; -// add the styles to the DOM -var update = __webpack_require__(3)("1096aefc", content, true); -// Hot Module Replacement -if(false) { - // When the styles change, update the <style> tags - if(!content.locals) { - module.hot.accept("!!../../node_modules/css-loader/index.js?minimize!../../node_modules/vue-loader/lib/style-compiler/index.js?{\"id\":\"data-v-4f6bf458\",\"scoped\":true,\"hasInlineConfig\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./prompt.vue", function() { - var newContent = require("!!../../node_modules/css-loader/index.js?minimize!../../node_modules/vue-loader/lib/style-compiler/index.js?{\"id\":\"data-v-4f6bf458\",\"scoped\":true,\"hasInlineConfig\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./prompt.vue"); - if(typeof newContent === 'string') newContent = [[module.id, newContent, '']]; - update(newContent); - }); - } - // When the module is disposed, remove the <style> tags - module.hot.dispose(function() { update(); }); -} - -/***/ }), -/* 45 */ -/***/ (function(module, exports, __webpack_require__) { - -// style-loader: Adds some css to the DOM by adding a <style> tag - -// load the styles -var content = __webpack_require__(22); -if(typeof content === 'string') content = [[module.i, content, '']]; -if(content.locals) module.exports = content.locals; -// add the styles to the DOM -var update = __webpack_require__(3)("58a0689d", content, true); -// Hot Module Replacement -if(false) { - // When the styles change, update the <style> tags - if(!content.locals) { - module.hot.accept("!!../../node_modules/css-loader/index.js?minimize!../../node_modules/vue-loader/lib/style-compiler/index.js?{\"id\":\"data-v-7342b363\",\"scoped\":false,\"hasInlineConfig\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./markdown.vue", function() { - var newContent = require("!!../../node_modules/css-loader/index.js?minimize!../../node_modules/vue-loader/lib/style-compiler/index.js?{\"id\":\"data-v-7342b363\",\"scoped\":false,\"hasInlineConfig\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./markdown.vue"); - if(typeof newContent === 'string') newContent = [[module.id, newContent, '']]; - update(newContent); - }); - } - // When the module is disposed, remove the <style> tags - module.hot.dispose(function() { update(); }); -} - -/***/ }), -/* 46 */ -/***/ (function(module, exports) { - -/** - * Translates the list format produced by css-loader into something - * easier to manipulate. - */ -module.exports = function listToStyles (parentId, list) { - var styles = [] - var newStyles = {} - for (var i = 0; i < list.length; i++) { - var item = list[i] - var id = item[0] - var css = item[1] - var media = item[2] - var sourceMap = item[3] - var part = { - id: parentId + ':' + i, - css: css, - media: media, - sourceMap: sourceMap - } - if (!newStyles[id]) { - styles.push(newStyles[id] = { id: id, parts: [part] }) - } else { - newStyles[id].parts.push(part) - } - } - return styles -} - - -/***/ }), -/* 47 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var Notebook = __webpack_require__(6); - -module.exports = { - install: function install(_vue) { - _vue.component('notebook-lab', Notebook); - } -}; - -/***/ }) -/******/ ]); -});
\ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 90ba39a3251..8f38fb4a9a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1119,6 +1119,14 @@ cli-width@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" +clipboard@^1.5.5: + version "1.6.1" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-1.6.1.tgz#65c5b654812466b0faab82dc6ba0f1d2f8e4be53" + dependencies: + good-listener "^1.2.0" + select "^1.1.2" + tiny-emitter "^1.0.0" + cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -1596,6 +1604,10 @@ delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" +delegate@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.1.2.tgz#1e1bc6f5cadda6cb6cbf7e6d05d0bcdd5712aebe" + delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" @@ -2497,6 +2509,12 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" +good-listener@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + dependencies: + delegate "^3.1.2" + got@^3.2.0: version "3.3.1" resolved "https://registry.yarnpkg.com/got/-/got-3.3.1.tgz#e5d0ed4af55fc3eef4d56007769d98192bcb2eca" @@ -3554,6 +3572,10 @@ map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" +marked@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" + math-expression-evaluator@^1.2.14: version "1.2.16" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.16.tgz#b357fa1ca9faefb8e48d10c14ef2bcb2d9f0a7c9" @@ -4415,6 +4437,12 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +prismjs@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.6.0.tgz#118d95fb7a66dba2272e343b345f5236659db365" + optionalDependencies: + clipboard "^1.5.5" + private@^0.1.6: version "0.1.7" resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" @@ -4873,6 +4901,10 @@ select2@3.5.2-browserify: version "3.5.2-browserify" resolved "https://registry.yarnpkg.com/select2/-/select2-3.5.2-browserify.tgz#dc4dafda38d67a734e8a97a46f0d3529ae05391d" +select@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" @@ -5368,6 +5400,10 @@ timers-browserify@^2.0.2: dependencies: setimmediate "^1.0.4" +tiny-emitter@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-1.1.0.tgz#ab405a21ffed814a76c19739648093d70654fecb" + tmp@0.0.28, tmp@0.0.x: version "0.0.28" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.28.tgz#172735b7f614ea7af39664fa84cf0de4e515d120" |