Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • rspeicher/gitlab
  • reprazent/gitlab
  • mwasilewski-gitlab/gitlab
  • mlapierre/gitlab
  • gl-gitaly/gitlab
  • gitlab-org/gitlab
  • 1and1_ebusiness/gitlab-ee
  • marin/gitlab-ee
  • max-group/gitlab-ee
  • cirosantilli/gitlab-ee
  • cernvcs/gitlab-ee
  • chrisrohr/gitlab-ee
  • stanhu/gitlab-ee
  • ealcantara/gitlab
  • sijis/gitlab-ee
  • kalibyrn/gitlab-ee
  • bbodenmiller/gitlab-ee
  • cvd/gitlab-ee
  • alexwarren/gitlab-ee
  • j.seto/gitlab
  • cmiskell/gitlab
  • Ashley/gitlab-ee
  • kkm/gitlab-ee
  • haynes/gitlab-ee
  • dblessing/gitlab-ee
  • allison.browne/gitlab
  • singingwolfboy/gitlab-ee
  • coderhugo/gitlab-ee
  • axil/gitlab-ee
  • truongsinh/gitlab-ee
  • tensky/gitlab-ee
  • rymai/gitlab-ee
  • jt-gitlab/gitlab-ee
  • patricio/gitlab-ee
  • b.lashen/gitlab-ee
  • acroitor/gitlab
  • rosiv/gitlab-ee
  • sune-keller/gitlab-ee
  • wiget/gitlab-ee
  • bandel/gitlab-ee
  • e4r7hbug/gitlab-ee
  • chaosaffe/gitlab-ee
  • yannick-croissant/gitlab-ee
  • jameslopez/gitlab-ee
  • xellor/gitlab-ee
  • ymotiongroup/gitlab-ee
  • cwilcox/gitlab-ee
  • daniel.hoffmann/gitlab-ee
  • johnnyeric/gitlab-ee
  • pidge/gitlab-ee
  • Posp/gitlab-ee
  • jonafato/gitlab-ee
  • Quintasan/gitlab
  • shobra/gitlab-ee
  • sleepyknife/gitlab-ee
  • yorickpeterse/gitlab
  • abualy/gitlab-ee
  • ci-test-user-mk/gitlab
  • jogo/gitlab-ee
  • foxnewsnetwork/gitlab-ee
  • riemers/gitlab-ee
  • pacoguzman/gitlab-ee
  • usr01/gitlab-ee
  • samuel.bernard/gitlab-ee
  • codelust/gitlab-ee
  • takitak/gitlab-ee
  • ftasdelen/gitlab-ee
  • qhcthanh/gitlab-ee
  • clairton/gitlab-ee
  • cuongtm/gitlab-ee
  • m5/gitlab-ee
  • Sivapuram/gitlab-ee
  • sbeleidy/gitlab-ee
  • baparici/gitlab-ee
  • Hubbitus/gitlab-ee
  • lbennett/gitlab-ee
  • klml/gitlab-ee
  • jaydeland/gitlab-ee
  • lupine/gitlab-ee
  • leftathome/gitlab-ee
  • ianb/gitlab-ee
  • mumayank/gitlab-ee
  • nagoyamavps/gitlab-ee
  • pattyhama/gitlab-ee
  • momirza/gitlab-ee
  • BhavaniM/gitlab-ee
  • morefice/gitlab
  • splattael-staging/gitlab
  • toanalien/gitlab-ee
  • clever_usr_name/gitlab-ee
  • oscar-lopez/gitlab-ee
  • svansteenis/gitlab-ee
  • prashtest/gitlab-ee
  • bonsai/gitlab-ee
  • graingert/gitlab-ee
  • niijv/gitlab-ee
  • abdiasshaw/gitlab-ee
  • peter9208/gitlab-ee
  • gforcada/gitlab-ee
  • broftkd/gitlab-ee
  • mkobel/gitlab-ee
  • mikaelz/gitlab-ee
  • OdNairy/gitlab-ee
  • christinebeaubrun/gitlab-ee
  • haakoo/gitlab-ee
  • Rencs/gitlab-ee
  • marcia/gitlab-ee
  • dehvmartins/gitlab-ee
  • rouzbeh84/gitlab-ee
  • gjunker/gitlab-ee
  • nick.thomas/gitlab-ee
  • heijmans/gitlab-ee
  • s.ghafarpour/gitlab-ee
  • markglenfletcher1/gitlab-ee
  • Benno/gitlab-ee
  • s2gluser/gitlab-ee
  • hazelyang/gitlab-ee
  • dewetblomerus/gitlab-ee
  • chrisbelyea/gitlab-ee
  • nick.volynkin/gitlab-ee
  • sevenseacat/gitlab-ee
  • yuanchenxi95/gitlab-ee
  • andyli/gitlab-ee
  • nacredata/gitlab-ee
  • srkaycg_admin/gitlab-ee
  • tagyangyang/gitlab-ee
  • miroslav.meca/gitlab-ee
  • cafed00d/gitlab-ee
  • iOrange/gitlab-ee
  • shackledtodesk/gitlab-ee
  • kalleva/gitlab-ee
  • paulsen.jan/gitlab-ee
  • hu19891110/gitlab-ee
  • gmeans/gitlab-ee
  • nithin2/gitlab-ee
  • dbelova/gitlab-ee
  • GeorgConradi/gitlab-ee
  • iunet/gitlab-ee
  • ephemeric/gitlab-ee
  • wendy0402/gitlab-ee
  • phil7/gitlab-ee
  • Eichi4Eichler/gitlab-ee
  • Munken/gitlab-ee
  • clim/gitlab-ee
  • averyduffin/gitlab-ee
  • DKovel/gitlab-ee
  • katrinleinweber/gitlab-ee
  • tmaier/gitlab-ee
  • Shahriar_Rabbi/gitlab-ee
  • Stretch96/gitlab-ee
  • brennanroberts/gitlab-ee
  • sanyatuning/gitlab-ee
  • hkrutzer/gitlab-ee
  • visualrobots/gitlab-ee
  • jieme/gitlab-ee
  • vansch/gitlab-ee
  • smuthusamy.fivedtech/gitlab-ee
  • almtoolbox/gitlab-ee
  • niketgupta6590/gitlab-ee
  • d.demichelis/gitlab-ee
  • LeclercA/gitlab-ee
  • bpietraga/gitlab-ee
  • ivikash/gitlab-ee
  • TobbenTM/gitlab-ee
  • YarNayar/gitlab-ee
  • dcondrey/gitlab-ee
  • atronah/gitlab-ee
  • mindupper/gitlab-ee
  • zyfran/gitlab-ee
  • savitojs/gitlab-ee
  • vino.v/gitlab-ee
  • athar/gitlab-ee
  • me63/gitlab-ee
  • l00mi/gitlab-ee
  • trentontri/gitlab-ee
  • peterlebrun/gitlab-ee
  • gwawr/gitlab-ee
  • isolation85/gitlab-ee
  • timothyandrew/gitlab-ee
  • shawonsoyket439/gitlab-ee
  • afolson/gitlab-ee
  • ismail-s/gitlab-ee
  • peterramsing/gitlab-ee
  • kason/gitlab-ee
  • al1_andre/gitlab-ee
  • pchojnacki/gitlab-ee
  • juliusv/gitlab-ee
  • scallopedllama/gitlab-ee
  • frech/gitlab-ee
  • z9g9l9/gitlab-ee
  • jamiekaw/gitlab-ee
  • mrburrito/gitlab-ee
  • headcrabmeat/gitlab-ee
  • cristiantmbr/gitlab-ee
  • revuel/gitlab-ee
  • Nnidyu/gitlab-ee
  • MrCirwos/gitlab-ee
  • Gutenevv/gitlab-ee
  • jmeyo/gitlab-ee
  • ollie314/gitlab-ee
  • sang9402/gitlab-ee
  • mickael9/gitlab-ee
  • vsizov/gitlab-ee
  • dosuken123/gitlab-ee
  • geoandri/gitlab-ee
  • afrastgeek/gitlab-ee
  • steveschooncts/gitlab-ee
  • dinsaw/gitlab-ee
  • xqua/gitlab-ee
  • smith-kyle/gitlab-ee
  • Mattlk13/gitlab-ee
  • andy_b_84/gitlab-ee
  • raansari/gitlab-ee
  • abitduck/gitlab-ee
  • mgresko/gitlab-ee
  • sidewinder12s/gitlab-ee
  • andresca/gitlab-ee
  • ccrebolder/gitlab-ee
  • rodrigo.pereira1/gitlab-ee
  • mohideen.rahuman/gitlab-ee
  • hebbet/gitlab-ee
  • smcgivern/gitlab-ee
  • heapifyman/gitlab-ee
  • TeNNoX/gitlab-ee
  • herryLi/gitlab-ee
  • AlexKalinin/gitlab-ee
  • vincedmg/gitlab-ee
  • martflu/gitlab-ee
  • derik/gitlab-ee
  • Ruby-and-Friends/gitlab-ee
  • wojciechlisik/gitlab-ee
  • winniehell-gitlab/gitlab-ee
  • Vaidehee5/gitlab-ee
  • vignesh.ravichandran02/gitlab-ee
  • tanyan2004/gitlab-ee
  • gitlabproject_s/gitlab-ee
  • virth/gitlab-ee
  • tmlee/gitlab-ee
  • hwdegroot/gitlab-ee
  • kybae/gitlab-ee
  • xiaogang_gitlab/gitlab-ee
  • jabber/gitlab-ee
  • eswar.madhira/gitlab-ee
  • alshamiri2/gitlab-ee
  • ba2014sheer/gitlab-ee
  • paulcodiny/gitlab-ee
  • glabio/gitlab-ee
  • lenghan1991/gitlab-ee
  • peterl/gitlab-ee
  • lucianomx/gitlab-ee
  • jbrandhorst/gitlab-ee
  • abushoeb/gitlab-ee
  • shellthor/gitlab-ee
  • jameshclrk/gitlab-ee
  • jontdelorme/gitlab-ee
  • tzc_007/gitlab-ee
  • indobits/gitlab-ee
  • dturner_ts/gitlab-ee
  • gauravkk22/gitlab-ee
  • andy9775/gitlab-ee
  • vladel/gitlab-ee
  • hakulatata99/gitlab-ee
  • lee0824/gitlab-ee
  • pk-codebox-evo/gitlab-ee
  • feshu/gitlab-ee
  • techguru/gitlab-ee
  • ei-grad/gitlab-ee
  • mccomput3rfr3ak/gitlab-ee
  • winnetou/gitlab-ee
  • julian-poidevin/gitlab-ee
  • arihantar/gitlab-ee
  • Trilom/gitlab-ee
  • Waysb1/gitlab-ee
  • jjung/gitlab-ee
  • xiaole/gitlab-ee
  • kikipq/gitlab-ee
  • rpadovani/gitlab-ee
  • zsturgess/gitlab-ee
  • mishunov/gitlab
  • nodeable/gitlab-ee
  • m1guelpiedrafita/gitlab-ee
  • jonas1/gitlab-ee
  • imranh/gitlab-ee
  • vitor.tyburski/gitlab-ee
  • pavel-voronin/gitlab-ee
  • alizadeh/gitlab-ee
  • aaaaaaq/gitlab-ee
  • JaKXz/gitlab-ee
  • umirra/gitlab-ee
  • jjcarstens/gitlab-ee
  • jenibella/gitlab-ee
  • hnk/gitlab-ee
  • roccolangeweg/gitlab-ee
  • batok/gitlab-ee
  • rajgomase24/gitlab-ee
  • qmnguyen0711/gitlab
  • 413063135/gitlab-ee
  • josephmarty/gitlab-ee
  • rdumont/gitlab-ee
  • gucong3000/gitlab-ee
  • ckatanda/gitlab-ee
  • overflowsith/gitlab-ee
  • TheJaredWilcurt/gitlab-ee
  • Riktos/gitlab-ee
  • losingle/gitlab-ee
  • mlushpenko/gitlab-ee
  • ericy_ts/gitlab-ee
  • fadb/gitlab-ee
  • dbvid/gitlab-ee
  • thejacer87/gitlab-ee
  • eli.boyarski/gitlab-ee
  • baldwinSPC/gitlab-ee
  • baldwinmathew/gitlab-ee
  • gsmethells/gitlab-ee
  • funkypenguin/gitlab-ee
  • rrentfro/gitlab-ee
  • M1TKO/gitlab-ee
  • SuriyaaKudoIsc/gitlab-ee
  • lmsurprenant/gitlab-ee
  • kay54088/gitlab-ee
  • pablo.catalina/gitlab-ee
  • xji/gitlab-ee
  • iscorer/gitlab-ee
  • kenny-evitt/gitlab-ee
  • Francis_Jude/gitlab-ee
  • xukaierwen/gitlab-ee
  • mustafayildirim/gitlab-ee
  • hh1/gitlab-ee
  • clamp27/gitlab-ee
  • UIPCO/gitlab-ee
  • chaase/gitlab-ee
  • matt.faure/gitlab-ee
  • wstomv/gitlab-ee
  • childNode/gitlab-ee
  • LockiStrike/gitlab-ee
  • Habiballah786/gitlab-ee
  • natebird/gitlab-ee
  • tamcv/gitlab-ee
  • adligithub/gitlab-ee
  • SuperDragon317/gitlab-ee
  • pkoretic/gitlab-ee
  • schoh/gitlab-ee
  • kpankonen/gitlab-ee
  • madnut_ua/gitlab-ee
  • smoothsailing/gitlab-ee
  • TimoSolo/gitlab-ee
  • collen/gitlab-ee
  • 0_0_0/gitlab-ee
  • innerwhisper/gitlab-ee
  • issue-reproduce-forks/gitlab-ee
  • szpak/gitlab-ee
  • zullusa/gitlab-ee
  • jamatute/gitlab-ee
  • mauriciomeirelles/gitlab-ee
  • anarcat/gitlab-ee
  • Shura/gitlab-ee
  • polarise/gitlab-ee
  • ecbrodie/gitlab-ee
  • odromark/gitlab-ee
  • senk/gitlab-ee
  • hiroponz/gitlab-ee
  • rawkode/gitlab-ee
  • HaPPyWaLLaCe/gitlab-ee
  • FeditskiyRoman/gitlab-ee
  • slrz/gitlab-ee
  • realsobek/gitlab-ee
  • Eternal21/gitlab-ee
  • leungpeng/gitlab-ee
  • nprabhu02/gitlab-ee
  • CodingGroup/gitlab-ee
  • smhoekstra/gitlab-ee
  • zeih/gitlab-ee
  • biancaghiurutan/gitlab-ee
  • bstrong/gitlab-ee
  • nap/gitlab-ee
  • mollybeth/gitlab-ee
  • Jeismeier/gitlab-ee
  • bouland/gitlab-ee
  • poneytruand/gitlab-ee
  • robotmay/gitlab
380 results
Show changes
Commits on Source (503)
Showing
with 267 additions and 190 deletions
Loading
@@ -55,7 +55,7 @@ stages:
Loading
@@ -55,7 +55,7 @@ stages:
   
.use-pg: &use-pg .use-pg: &use-pg
services: services:
- postgres:latest - postgres:9.2
- redis:alpine - redis:alpine
- elasticsearch:5.3 - elasticsearch:5.3
   
Loading
@@ -68,6 +68,7 @@ stages:
Loading
@@ -68,6 +68,7 @@ stages:
.only-master-and-ee-or-mysql: &only-master-and-ee-or-mysql .only-master-and-ee-or-mysql: &only-master-and-ee-or-mysql
only: only:
- /mysql/ - /mysql/
- /-stable$/
- master@gitlab-org/gitlab-ce - master@gitlab-org/gitlab-ce
- master@gitlab/gitlabhq - master@gitlab/gitlabhq
- tags@gitlab-org/gitlab-ce - tags@gitlab-org/gitlab-ce
Loading
@@ -89,7 +90,7 @@ stages:
Loading
@@ -89,7 +90,7 @@ stages:
- JOB_NAME=( $CI_JOB_NAME ) - JOB_NAME=( $CI_JOB_NAME )
- export CI_NODE_INDEX=${JOB_NAME[-2]} - export CI_NODE_INDEX=${JOB_NAME[-2]}
- export CI_NODE_TOTAL=${JOB_NAME[-1]} - 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_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export KNAPSACK_GENERATE_REPORT=true - export KNAPSACK_GENERATE_REPORT=true
- export CACHE_CLASSES=true - export CACHE_CLASSES=true
- cp ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH} - cp ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
Loading
@@ -120,7 +121,7 @@ stages:
Loading
@@ -120,7 +121,7 @@ stages:
- JOB_NAME=( $CI_JOB_NAME ) - JOB_NAME=( $CI_JOB_NAME )
- export CI_NODE_INDEX=${JOB_NAME[-2]} - export CI_NODE_INDEX=${JOB_NAME[-2]}
- export CI_NODE_TOTAL=${JOB_NAME[-1]} - 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_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export KNAPSACK_GENERATE_REPORT=true - export KNAPSACK_GENERATE_REPORT=true
- export CACHE_CLASSES=true - export CACHE_CLASSES=true
- cp ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH} - cp ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
Loading
@@ -154,11 +155,13 @@ stages:
Loading
@@ -154,11 +155,13 @@ stages:
# Trigger a package build on omnibus-gitlab repository # Trigger a package build on omnibus-gitlab repository
   
build-package: build-package:
image: ruby:2.3-alpine
before_script: [] before_script: []
services: [] services: []
variables: variables:
SETUP_DB: "false" SETUP_DB: "false"
USE_BUNDLE_INSTALL: "false" USE_BUNDLE_INSTALL: "false"
EE_PACKAGE: "true"
stage: build stage: build
when: manual when: manual
script: script:
Loading
@@ -183,8 +186,8 @@ update-knapsack:
Loading
@@ -183,8 +186,8 @@ update-knapsack:
<<: *only-canonical-masters <<: *only-canonical-masters
stage: post-test stage: post-test
script: script:
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_pg_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 - 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' - '[[ -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 - rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json
   
Loading
Loading
Loading
@@ -971,7 +971,7 @@ RSpec/DescribeSymbol:
Loading
@@ -971,7 +971,7 @@ RSpec/DescribeSymbol:
RSpec/DescribedClass: RSpec/DescribedClass:
Enabled: true Enabled: true
   
# Configuration parameters: CustomIncludeMethods. # Checks if an example group does not include any tests.
RSpec/EmptyExampleGroup: RSpec/EmptyExampleGroup:
Enabled: true Enabled: true
CustomIncludeMethods: CustomIncludeMethods:
Loading
@@ -998,6 +998,10 @@ RSpec/ExampleWording:
Loading
@@ -998,6 +998,10 @@ RSpec/ExampleWording:
RSpec/ExpectActual: RSpec/ExpectActual:
Enabled: true Enabled: true
   
# Checks for opportunities to use `expect { … }.to output`.
RSpec/ExpectOutput:
Enabled: true
# Checks the file and folder naming of the spec file. # Checks the file and folder naming of the spec file.
RSpec/FilePath: RSpec/FilePath:
Enabled: true Enabled: true
Loading
Loading
Loading
@@ -18,10 +18,6 @@ RSpec/EmptyLineAfterFinalLet:
Loading
@@ -18,10 +18,6 @@ RSpec/EmptyLineAfterFinalLet:
RSpec/EmptyLineAfterSubject: RSpec/EmptyLineAfterSubject:
Enabled: false Enabled: false
   
# Offense count: 3
RSpec/ExpectOutput:
Enabled: false
# Offense count: 72 # Offense count: 72
# Configuration parameters: EnforcedStyle, SupportedStyles. # Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: implicit, each, example # SupportedStyles: implicit, each, example
Loading
Loading
5.0.3 5.0.4
9.2.0-pre 9.3.0-pre
/* eslint-disable no-var, wrap-iife, func-names, space-before-function-paren, camelcase, no-unused-vars, quotes, object-shorthand, one-var, one-var-declaration-per-line, prefer-arrow-callback, comma-dangle, prefer-template, no-else-return, yoda, prefer-rest-params, prefer-spread, max-len */ /* eslint-disable no-var, wrap-iife, func-names, space-before-function-paren, camelcase, no-unused-vars, quotes, object-shorthand, one-var, one-var-declaration-per-line, prefer-arrow-callback, comma-dangle, prefer-template, no-else-return, yoda, prefer-rest-params, prefer-spread, max-len */
/* global Api */ import Api from './api';
   
var slice = [].slice; var slice = [].slice;
   
Loading
Loading
/* eslint-disable func-names, space-before-function-paren, quotes, object-shorthand, camelcase, no-var, comma-dangle, prefer-arrow-callback, quote-props, no-param-reassign, max-len */ import $ from 'jquery';
   
var Api = { const Api = {
groupsPath: '/api/:version/groups.json', groupsPath: '/api/:version/groups.json',
groupPath: '/api/:version/groups/:id.json', groupPath: '/api/:version/groups/:id.json',
namespacesPath: '/api/:version/namespaces.json', namespacesPath: '/api/:version/namespaces.json',
Loading
@@ -13,165 +13,190 @@ var Api = {
Loading
@@ -13,165 +13,190 @@ var Api = {
ldapGroupsPath: '/api/:version/ldap/:provider/groups.json', ldapGroupsPath: '/api/:version/ldap/:provider/groups.json',
dockerfilePath: '/api/:version/templates/dockerfiles/:key', dockerfilePath: '/api/:version/templates/dockerfiles/:key',
issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key', issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key',
group: function(group_id, callback) { usersPath: '/api/:version/users.json',
var url = Api.buildUrl(Api.groupPath) group(groupId, callback) {
.replace(':id', group_id); const url = Api.buildUrl(Api.groupPath)
return $.ajax({ .replace(':id', groupId);
url: url,
dataType: 'json'
}).done(function(group) {
return callback(group);
});
},
users: function(search, options, callback = $.noop) {
var url = Api.buildUrl('/autocomplete/users.json');
return $.ajax({ return $.ajax({
url, url,
data: $.extend({ dataType: 'json',
search, })
per_page: 20 .done(group => callback(group));
}, options),
dataType: 'json'
}).done(callback);
}, },
// Return groups list. Filtered by query // Return groups list. Filtered by query
groups: function(query, options, callback = $.noop) { groups(query, options, callback = $.noop) {
var url = Api.buildUrl(Api.groupsPath); const url = Api.buildUrl(Api.groupsPath);
return $.ajax({ return $.ajax({
url: url, url,
data: $.extend({ data: Object.assign({
search: query, search: query,
per_page: 20 per_page: 20,
}, options), }, options),
dataType: 'json' dataType: 'json',
}).done(function(groups) { })
return callback(groups); .done(groups => callback(groups));
});
}, },
// Return namespaces list. Filtered by query // Return namespaces list. Filtered by query
namespaces: function(query, callback) { namespaces(query, callback) {
var url = Api.buildUrl(Api.namespacesPath); const url = Api.buildUrl(Api.namespacesPath);
return $.ajax({ return $.ajax({
url: url, url,
data: { data: {
search: query, search: query,
per_page: 20 per_page: 20,
}, },
dataType: 'json' dataType: 'json',
}).done(function(namespaces) { }).done(namespaces => callback(namespaces));
return callback(namespaces);
});
}, },
// Return projects list. Filtered by query // Return projects list. Filtered by query
projects: function(query, options, callback) { projects(query, options, callback) {
var url = Api.buildUrl(Api.projectsPath); const url = Api.buildUrl(Api.projectsPath);
return $.ajax({ return $.ajax({
url: url, url,
data: $.extend({ data: Object.assign({
search: query, search: query,
per_page: 20, per_page: 20,
membership: true membership: true,
}, options), }, options),
dataType: 'json' dataType: 'json',
}).done(function(projects) { })
return callback(projects); .done(projects => callback(projects));
});
}, },
newLabel: function(namespace_path, project_path, data, callback) {
var url = Api.buildUrl(Api.labelsPath) newLabel(namespacePath, projectPath, data, callback) {
.replace(':namespace_path', namespace_path) const url = Api.buildUrl(Api.labelsPath)
.replace(':project_path', project_path); .replace(':namespace_path', namespacePath)
.replace(':project_path', projectPath);
return $.ajax({ return $.ajax({
url: url, url,
type: 'POST', type: 'POST',
data: { 'label': data }, data: { label: data },
dataType: 'json' dataType: 'json',
}).done(function(label) { })
return callback(label); .done(label => callback(label))
}).error(function(message) { .error(message => callback(message.responseJSON));
return callback(message.responseJSON);
});
}, },
// Return group projects list. Filtered by query // Return group projects list. Filtered by query
groupProjects: function(group_id, query, callback) { groupProjects(groupId, query, callback) {
var url = Api.buildUrl(Api.groupProjectsPath) const url = Api.buildUrl(Api.groupProjectsPath)
.replace(':id', group_id); .replace(':id', groupId);
return $.ajax({ return $.ajax({
url: url, url,
data: { data: {
search: query, search: query,
per_page: 20 per_page: 20,
}, },
dataType: 'json' dataType: 'json',
}).done(function(projects) { })
return callback(projects); .done(projects => callback(projects));
});
}, },
// Return text for a specific license // Return text for a specific license
licenseText: function(key, data, callback) { licenseText(key, data, callback) {
var url = Api.buildUrl(Api.licensePath) const url = Api.buildUrl(Api.licensePath)
.replace(':key', key); .replace(':key', key);
return $.ajax({ return $.ajax({
url: url, url,
data: data data,
}).done(function(license) { })
return callback(license); .done(license => callback(license));
});
}, },
gitignoreText: function(key, callback) {
var url = Api.buildUrl(Api.gitignorePath) gitignoreText(key, callback) {
const url = Api.buildUrl(Api.gitignorePath)
.replace(':key', key); .replace(':key', key);
return $.get(url, function(gitignore) { return $.get(url, gitignore => callback(gitignore));
return callback(gitignore);
});
}, },
gitlabCiYml: function(key, callback) {
var url = Api.buildUrl(Api.gitlabCiYmlPath) gitlabCiYml(key, callback) {
const url = Api.buildUrl(Api.gitlabCiYmlPath)
.replace(':key', key); .replace(':key', key);
return $.get(url, function(file) { return $.get(url, file => callback(file));
return callback(file);
});
}, },
dockerfileYml: function(key, callback) {
var url = Api.buildUrl(Api.dockerfilePath).replace(':key', key); dockerfileYml(key, callback) {
const url = Api.buildUrl(Api.dockerfilePath).replace(':key', key);
$.get(url, callback); $.get(url, callback);
}, },
issueTemplate: function(namespacePath, projectPath, key, type, callback) {
var url = Api.buildUrl(Api.issuableTemplatePath) issueTemplate(namespacePath, projectPath, key, type, callback) {
const url = Api.buildUrl(Api.issuableTemplatePath)
.replace(':key', key) .replace(':key', key)
.replace(':type', type) .replace(':type', type)
.replace(':project_path', projectPath) .replace(':project_path', projectPath)
.replace(':namespace_path', namespacePath); .replace(':namespace_path', namespacePath);
$.ajax({ $.ajax({
url: url, url,
dataType: 'json' dataType: 'json',
}).done(function(file) { })
callback(null, file); .done(file => callback(null, file))
}).error(callback); .error(callback);
}, },
buildUrl: function(url) {
if (gon.relative_url_root != null) { users(query, options) {
url = gon.relative_url_root + url; const url = Api.buildUrl(this.usersPath);
} return Api.wrapAjaxCall({
return url.replace(':version', gon.api_version); url,
data: Object.assign({
search: query,
per_page: 20,
}, options),
dataType: 'json',
});
}, },
ldap_groups: function(query, provider, callback) {
var url; approverUsers(search, options, callback = $.noop) {
url = Api.buildUrl(Api.ldapGroupsPath); const url = Api.buildUrl('/autocomplete/users.json');
url = url.replace(':provider', provider);
return $.ajax({ return $.ajax({
url: url, url,
data: { data: $.extend({
search,
per_page: 20,
}, options),
dataType: 'json',
}).done(callback);
},
ldap_groups(query, provider, callback) {
const url = Api.buildUrl(this.ldapGroupsPath).replace(':provider', provider);
return Api.wrapAjaxCall({
url,
data: Object.assign({
private_token: gon.api_token, private_token: gon.api_token,
search: query, search: query,
per_page: 20, per_page: 20,
active: true active: true,
}, }),
dataType: 'json' dataType: 'json',
}).done(function(groups) { })
return callback(groups); .done(groups => callback(groups));
},
buildUrl(url) {
let urlRoot = '';
if (gon.relative_url_root != null) {
urlRoot = gon.relative_url_root;
}
return urlRoot + url.replace(':version', gon.api_version);
},
wrapAjaxCall(options) {
return new Promise((resolve, reject) => {
// jQuery 2 is not Promises/A+ compatible (missing catch)
$.ajax(options) // eslint-disable-line promise/catch-or-return
.then(data => resolve(data),
(jqXHR, textStatus, errorThrown) => {
const error = new Error(`${options.url}: ${errorThrown}`);
error.textStatus = textStatus;
reject(error);
},
);
}); });
} },
}; };
   
window.Api = Api; export default Api;
/* global Api */ import Api from './api';
   
export default class ApproversSelect { export default class ApproversSelect {
constructor() { constructor() {
Loading
@@ -46,7 +46,7 @@ export default class ApproversSelect {
Loading
@@ -46,7 +46,7 @@ export default class ApproversSelect {
skip_users: ApproversSelect.getApprovers(this.fieldNames[0], '.js-approver'), skip_users: ApproversSelect.getApprovers(this.fieldNames[0], '.js-approver'),
project_id: $('#project_id').val(), project_id: $('#project_id').val(),
}; };
return Api.users(term, options); return Api.approverUsers(term, options);
} }
   
handleSelectChange(e) { handleSelectChange(e) {
Loading
Loading
/* global Api */
export default class FileTemplateSelector { export default class FileTemplateSelector {
constructor(mediator) { constructor(mediator) {
this.mediator = mediator; this.mediator = mediator;
Loading
@@ -65,4 +63,3 @@ export default class FileTemplateSelector {
Loading
@@ -65,4 +63,3 @@ export default class FileTemplateSelector {
this.reportSelection(opts); this.reportSelection(opts);
} }
} }
/* global Api */ import Api from '../../api';
   
import FileTemplateSelector from '../file_template_selector'; import FileTemplateSelector from '../file_template_selector';
   
Loading
Loading
/* global Api */ import Api from '../../api';
   
import FileTemplateSelector from '../file_template_selector'; import FileTemplateSelector from '../file_template_selector';
   
Loading
Loading
/* global Api */ import Api from '../../api';
   
import FileTemplateSelector from '../file_template_selector'; import FileTemplateSelector from '../file_template_selector';
   
Loading
Loading
/* global Api */ import Api from '../../api';
   
import FileTemplateSelector from '../file_template_selector'; import FileTemplateSelector from '../file_template_selector';
   
Loading
Loading
Loading
@@ -50,9 +50,9 @@ export default class BlobViewer {
Loading
@@ -50,9 +50,9 @@ export default class BlobViewer {
   
if (this.copySourceBtn) { if (this.copySourceBtn) {
this.copySourceBtn.addEventListener('click', () => { this.copySourceBtn.addEventListener('click', () => {
if (this.copySourceBtn.classList.contains('disabled')) return; if (this.copySourceBtn.classList.contains('disabled')) return this.copySourceBtn.blur();
   
this.switchToViewer('simple'); return this.switchToViewer('simple');
}); });
} }
} }
Loading
Loading
Loading
@@ -87,6 +87,7 @@ $(() => {
Loading
@@ -87,6 +87,7 @@ $(() => {
Store.rootPath = this.endpoint; Store.rootPath = this.endpoint;
   
this.filterManager = new FilteredSearchBoards(Store.filter, true, [(this.milestoneTitle ? 'milestone' : null)]); this.filterManager = new FilteredSearchBoards(Store.filter, true, [(this.milestoneTitle ? 'milestone' : null)]);
this.filterManager.setup();
   
// Listen for updateTokens event // Listen for updateTokens event
eventHub.$on('updateTokens', this.updateTokens); eventHub.$on('updateTokens', this.updateTokens);
Loading
Loading
import Vue from 'vue'; import Vue from 'vue';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../eventhub'; import eventHub from '../eventhub';
   
const Store = gl.issueBoards.BoardsStore; const Store = gl.issueBoards.BoardsStore;
Loading
@@ -38,6 +39,9 @@ gl.issueBoards.IssueCardInner = Vue.extend({
Loading
@@ -38,6 +39,9 @@ gl.issueBoards.IssueCardInner = Vue.extend({
maxCounter: 99, maxCounter: 99,
}; };
}, },
components: {
userAvatarLink,
},
computed: { computed: {
numberOverLimit() { numberOverLimit() {
return this.issue.assignees.length - this.limitBeforeCounter; return this.issue.assignees.length - this.limitBeforeCounter;
Loading
@@ -146,23 +150,16 @@ gl.issueBoards.IssueCardInner = Vue.extend({
Loading
@@ -146,23 +150,16 @@ gl.issueBoards.IssueCardInner = Vue.extend({
</span> </span>
</h4> </h4>
<div class="card-assignee"> <div class="card-assignee">
<a <user-avatar-link
class="has-tooltip js-no-trigger"
:href="assigneeUrl(assignee)"
:title="assigneeUrlTitle(assignee)"
v-for="(assignee, index) in issue.assignees" v-for="(assignee, index) in issue.assignees"
v-if="shouldRenderAssignee(index)" v-if="shouldRenderAssignee(index)"
data-container="body" class="js-no-trigger"
data-placement="bottom" :link-href="assigneeUrl(assignee)"
> :img-alt="avatarUrlTitle(assignee)"
<img :img-src="assignee.avatar"
class="avatar avatar-inline s20" :tooltip-text="assigneeUrlTitle(assignee)"
:src="assignee.avatar" tooltip-placement="bottom"
width="20" />
height="20"
:alt="avatarUrlTitle(assignee)"
/>
</a>
<span <span
class="avatar-counter has-tooltip" class="avatar-counter has-tooltip"
:title="assigneeCounterTooltip" :title="assigneeCounterTooltip"
Loading
Loading
Loading
@@ -13,6 +13,7 @@ export default {
Loading
@@ -13,6 +13,7 @@ export default {
FilteredSearchContainer.container = this.$el; FilteredSearchContainer.container = this.$el;
   
this.filteredSearch = new FilteredSearchBoards(this.store); this.filteredSearch = new FilteredSearchBoards(this.store);
this.filteredSearch.setup();
this.filteredSearch.removeTokens(); this.filteredSearch.removeTokens();
this.filteredSearch.handleInputPlaceholder(); this.filteredSearch.handleInputPlaceholder();
this.filteredSearch.toggleClearSearchButton(); this.filteredSearch.toggleClearSearchButton();
Loading
Loading
Loading
@@ -3,7 +3,6 @@
Loading
@@ -3,7 +3,6 @@
import Vue from 'vue'; import Vue from 'vue';
import queryData from '../../utils/query_data'; import queryData from '../../utils/query_data';
import loadingIcon from '../../../vue_shared/components/loading_icon.vue'; import loadingIcon from '../../../vue_shared/components/loading_icon.vue';
import './header'; import './header';
import './list'; import './list';
import './footer'; import './footer';
Loading
Loading
Loading
@@ -42,9 +42,7 @@ export default class FilteredSearchBoards extends gl.FilteredSearchManager {
Loading
@@ -42,9 +42,7 @@ export default class FilteredSearchBoards extends gl.FilteredSearchManager {
this.filteredSearchInput.dispatchEvent(new Event('input')); this.filteredSearchInput.dispatchEvent(new Event('input'));
} }
   
canEdit(token) { canEdit(tokenName) {
const tokenName = token.querySelector('.name').textContent.trim();
return this.cantEdit.indexOf(tokenName) === -1; return this.cantEdit.indexOf(tokenName) === -1;
} }
} }
Loading
@@ -18,12 +18,12 @@ const gfmRules = {
Loading
@@ -18,12 +18,12 @@ const gfmRules = {
}, },
}, },
TaskListFilter: { TaskListFilter: {
'input[type=checkbox].task-list-item-checkbox'(el, text) { 'input[type=checkbox].task-list-item-checkbox'(el) {
return `[${el.checked ? 'x' : ' '}]`; return `[${el.checked ? 'x' : ' '}]`;
}, },
}, },
ReferenceFilter: { ReferenceFilter: {
'.tooltip'(el, text) { '.tooltip'(el) {
return ''; return '';
}, },
'a.gfm:not([data-link=true])'(el, text) { 'a.gfm:not([data-link=true])'(el, text) {
Loading
@@ -39,15 +39,15 @@ const gfmRules = {
Loading
@@ -39,15 +39,15 @@ const gfmRules = {
}, },
}, },
TableOfContentsFilter: { TableOfContentsFilter: {
'ul.section-nav'(el, text) { 'ul.section-nav'(el) {
return '[[_TOC_]]'; return '[[_TOC_]]';
}, },
}, },
EmojiFilter: { EmojiFilter: {
'img.emoji'(el, text) { 'img.emoji'(el) {
return el.getAttribute('alt'); return el.getAttribute('alt');
}, },
'gl-emoji'(el, text) { 'gl-emoji'(el) {
return `:${el.getAttribute('data-name')}:`; return `:${el.getAttribute('data-name')}:`;
}, },
}, },
Loading
@@ -57,13 +57,13 @@ const gfmRules = {
Loading
@@ -57,13 +57,13 @@ const gfmRules = {
}, },
}, },
VideoLinkFilter: { VideoLinkFilter: {
'.video-container'(el, text) { '.video-container'(el) {
const videoEl = el.querySelector('video'); const videoEl = el.querySelector('video');
if (!videoEl) return false; if (!videoEl) return false;
   
return CopyAsGFM.nodeToGFM(videoEl); return CopyAsGFM.nodeToGFM(videoEl);
}, },
'video'(el, text) { 'video'(el) {
return `![${el.dataset.title}](${el.getAttribute('src')})`; return `![${el.dataset.title}](${el.getAttribute('src')})`;
}, },
}, },
Loading
@@ -74,19 +74,19 @@ const gfmRules = {
Loading
@@ -74,19 +74,19 @@ const gfmRules = {
'code.code.math[data-math-style=inline]'(el, text) { 'code.code.math[data-math-style=inline]'(el, text) {
return `$\`${text}\`$`; return `$\`${text}\`$`;
}, },
'span.katex-display span.katex-mathml'(el, text) { 'span.katex-display span.katex-mathml'(el) {
const mathAnnotation = el.querySelector('annotation[encoding="application/x-tex"]'); const mathAnnotation = el.querySelector('annotation[encoding="application/x-tex"]');
if (!mathAnnotation) return false; if (!mathAnnotation) return false;
   
return `\`\`\`math\n${CopyAsGFM.nodeToGFM(mathAnnotation)}\n\`\`\``; return `\`\`\`math\n${CopyAsGFM.nodeToGFM(mathAnnotation)}\n\`\`\``;
}, },
'span.katex-mathml'(el, text) { 'span.katex-mathml'(el) {
const mathAnnotation = el.querySelector('annotation[encoding="application/x-tex"]'); const mathAnnotation = el.querySelector('annotation[encoding="application/x-tex"]');
if (!mathAnnotation) return false; if (!mathAnnotation) return false;
   
return `$\`${CopyAsGFM.nodeToGFM(mathAnnotation)}\`$`; return `$\`${CopyAsGFM.nodeToGFM(mathAnnotation)}\`$`;
}, },
'span.katex-html'(el, text) { 'span.katex-html'(el) {
// We don't want to include the content of this element in the copied text. // We don't want to include the content of this element in the copied text.
return ''; return '';
}, },
Loading
@@ -95,7 +95,7 @@ const gfmRules = {
Loading
@@ -95,7 +95,7 @@ const gfmRules = {
}, },
}, },
SanitizationFilter: { SanitizationFilter: {
'a[name]:not([href]):empty'(el, text) { 'a[name]:not([href]):empty'(el) {
return el.outerHTML; return el.outerHTML;
}, },
'dl'(el, text) { 'dl'(el, text) {
Loading
@@ -143,7 +143,7 @@ const gfmRules = {
Loading
@@ -143,7 +143,7 @@ const gfmRules = {
}, },
}, },
MarkdownFilter: { MarkdownFilter: {
'br'(el, text) { 'br'(el) {
// Two spaces at the end of a line are turned into a BR // Two spaces at the end of a line are turned into a BR
return ' '; return ' ';
}, },
Loading
@@ -162,7 +162,7 @@ const gfmRules = {
Loading
@@ -162,7 +162,7 @@ const gfmRules = {
'blockquote'(el, text) { 'blockquote'(el, text) {
return text.trim().split('\n').map(s => `> ${s}`.trim()).join('\n'); return text.trim().split('\n').map(s => `> ${s}`.trim()).join('\n');
}, },
'img'(el, text) { 'img'(el) {
return `![${el.getAttribute('alt')}](${el.getAttribute('src')})`; return `![${el.getAttribute('alt')}](${el.getAttribute('src')})`;
}, },
'a.anchor'(el, text) { 'a.anchor'(el, text) {
Loading
@@ -222,10 +222,10 @@ const gfmRules = {
Loading
@@ -222,10 +222,10 @@ const gfmRules = {
'sup'(el, text) { 'sup'(el, text) {
return `^${text}`; return `^${text}`;
}, },
'hr'(el, text) { 'hr'(el) {
return '-----'; return '-----';
}, },
'table'(el, text) { 'table'(el) {
const theadEl = el.querySelector('thead'); const theadEl = el.querySelector('thead');
const tbodyEl = el.querySelector('tbody'); const tbodyEl = el.querySelector('tbody');
if (!theadEl || !tbodyEl) return false; if (!theadEl || !tbodyEl) return false;
Loading
@@ -233,11 +233,11 @@ const gfmRules = {
Loading
@@ -233,11 +233,11 @@ const gfmRules = {
const theadText = CopyAsGFM.nodeToGFM(theadEl); const theadText = CopyAsGFM.nodeToGFM(theadEl);
const tbodyText = CopyAsGFM.nodeToGFM(tbodyEl); const tbodyText = CopyAsGFM.nodeToGFM(tbodyEl);
   
return theadText + tbodyText; return [theadText, tbodyText].join('\n');
}, },
'thead'(el, text) { 'thead'(el, text) {
const cells = _.map(el.querySelectorAll('th'), (cell) => { const cells = _.map(el.querySelectorAll('th'), (cell) => {
let chars = CopyAsGFM.nodeToGFM(cell).trim().length + 2; let chars = CopyAsGFM.nodeToGFM(cell).length + 2;
   
let before = ''; let before = '';
let after = ''; let after = '';
Loading
@@ -262,10 +262,15 @@ const gfmRules = {
Loading
@@ -262,10 +262,15 @@ const gfmRules = {
return before + middle + after; return before + middle + after;
}); });
   
return `${text}|${cells.join('|')}|`; const separatorRow = `|${cells.join('|')}|`;
return [text, separatorRow].join('\n');
}, },
'tr'(el, text) { 'tr'(el) {
const cells = _.map(el.querySelectorAll('td, th'), cell => CopyAsGFM.nodeToGFM(cell).trim()); const cellEls = el.querySelectorAll('td, th');
if (cellEls.length === 0) return false;
const cells = _.map(cellEls, cell => CopyAsGFM.nodeToGFM(cell));
return `| ${cells.join(' | ')} |`; return `| ${cells.join(' | ')} |`;
}, },
}, },
Loading
@@ -273,12 +278,12 @@ const gfmRules = {
Loading
@@ -273,12 +278,12 @@ const gfmRules = {
   
class CopyAsGFM { class CopyAsGFM {
constructor() { constructor() {
$(document).on('copy', '.md, .wiki', (e) => { this.copyAsGFM(e, CopyAsGFM.transformGFMSelection); }); $(document).on('copy', '.md, .wiki', (e) => { CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformGFMSelection); });
$(document).on('copy', 'pre.code.highlight, .diff-content .line_content', (e) => { this.copyAsGFM(e, CopyAsGFM.transformCodeSelection); }); $(document).on('copy', 'pre.code.highlight, .diff-content .line_content', (e) => { CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformCodeSelection); });
$(document).on('paste', '.js-gfm-input', this.pasteGFM.bind(this)); $(document).on('paste', '.js-gfm-input', CopyAsGFM.pasteGFM);
} }
   
copyAsGFM(e, transformer) { static copyAsGFM(e, transformer) {
const clipboardData = e.originalEvent.clipboardData; const clipboardData = e.originalEvent.clipboardData;
if (!clipboardData) return; if (!clipboardData) return;
   
Loading
@@ -292,26 +297,59 @@ class CopyAsGFM {
Loading
@@ -292,26 +297,59 @@ class CopyAsGFM {
e.stopPropagation(); e.stopPropagation();
   
clipboardData.setData('text/plain', el.textContent); clipboardData.setData('text/plain', el.textContent);
clipboardData.setData('text/x-gfm', CopyAsGFM.nodeToGFM(el)); clipboardData.setData('text/x-gfm', this.nodeToGFM(el));
} }
   
pasteGFM(e) { static pasteGFM(e) {
const clipboardData = e.originalEvent.clipboardData; const clipboardData = e.originalEvent.clipboardData;
if (!clipboardData) return; if (!clipboardData) return;
   
const text = clipboardData.getData('text/plain');
const gfm = clipboardData.getData('text/x-gfm'); const gfm = clipboardData.getData('text/x-gfm');
if (!gfm) return; if (!gfm) return;
   
e.preventDefault(); e.preventDefault();
   
window.gl.utils.insertText(e.target, gfm); window.gl.utils.insertText(e.target, (textBefore, textAfter) => {
// If the text before the cursor contains an odd number of backticks,
// we are either inside an inline code span that starts with 1 backtick
// or a code block that starts with 3 backticks.
// This logic still holds when there are one or more _closed_ code spans
// or blocks that will have 2 or 6 backticks.
// This will break down when the actual code block contains an uneven
// number of backticks, but this is a rare edge case.
const backtickMatch = textBefore.match(/`/g);
const insideCodeBlock = backtickMatch && (backtickMatch.length % 2) === 1;
if (insideCodeBlock) {
return text;
}
return gfm;
});
} }
   
static transformGFMSelection(documentFragment) { static transformGFMSelection(documentFragment) {
// If the documentFragment contains more than just Markdown, don't copy as GFM. const gfmEls = documentFragment.querySelectorAll('.md, .wiki');
if (documentFragment.querySelector('.md, .wiki')) return null; switch (gfmEls.length) {
case 0: {
return documentFragment;
}
case 1: {
return gfmEls[0];
}
default: {
const allGfmEl = document.createElement('div');
for (let i = 0; i < gfmEls.length; i += 1) {
const lineEl = gfmEls[i];
allGfmEl.appendChild(lineEl);
allGfmEl.appendChild(document.createTextNode('\n\n'));
}
   
return documentFragment; return allGfmEl;
}
}
} }
   
static transformCodeSelection(documentFragment) { static transformCodeSelection(documentFragment) {
Loading
@@ -343,7 +381,7 @@ class CopyAsGFM {
Loading
@@ -343,7 +381,7 @@ class CopyAsGFM {
return codeEl; return codeEl;
} }
   
static nodeToGFM(node) { static nodeToGFM(node, respectWhitespaceParam = false) {
if (node.nodeType === Node.COMMENT_NODE) { if (node.nodeType === Node.COMMENT_NODE) {
return ''; return '';
} }
Loading
@@ -352,7 +390,9 @@ class CopyAsGFM {
Loading
@@ -352,7 +390,9 @@ class CopyAsGFM {
return node.textContent; return node.textContent;
} }
   
const text = this.innerGFM(node); const respectWhitespace = respectWhitespaceParam || (node.nodeName === 'PRE' || node.nodeName === 'CODE');
const text = this.innerGFM(node, respectWhitespace);
   
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
return text; return text;
Loading
@@ -366,7 +406,17 @@ class CopyAsGFM {
Loading
@@ -366,7 +406,17 @@ class CopyAsGFM {
   
if (!window.gl.utils.nodeMatchesSelector(node, selector)) continue; if (!window.gl.utils.nodeMatchesSelector(node, selector)) continue;
   
const result = func(node, text); let result;
if (func.length === 2) {
// if `func` takes 2 arguments, it depends on text.
// if there is no text, we don't need to generate GFM for this node.
if (text.length === 0) continue;
result = func(node, text);
} else {
result = func(node);
}
if (result === false) continue; if (result === false) continue;
   
return result; return result;
Loading
@@ -376,7 +426,7 @@ class CopyAsGFM {
Loading
@@ -376,7 +426,7 @@ class CopyAsGFM {
return text; return text;
} }
   
static innerGFM(parentNode) { static innerGFM(parentNode, respectWhitespace = false) {
const nodes = parentNode.childNodes; const nodes = parentNode.childNodes;
   
const clonedParentNode = parentNode.cloneNode(true); const clonedParentNode = parentNode.cloneNode(true);
Loading
@@ -386,13 +436,19 @@ class CopyAsGFM {
Loading
@@ -386,13 +436,19 @@ class CopyAsGFM {
const node = nodes[i]; const node = nodes[i];
const clonedNode = clonedNodes[i]; const clonedNode = clonedNodes[i];
   
const text = this.nodeToGFM(node); const text = this.nodeToGFM(node, respectWhitespace);
   
// `clonedNode.replaceWith(text)` is not yet widely supported // `clonedNode.replaceWith(text)` is not yet widely supported
clonedNode.parentNode.replaceChild(document.createTextNode(text), clonedNode); clonedNode.parentNode.replaceChild(document.createTextNode(text), clonedNode);
} }
   
return clonedParentNode.innerText || clonedParentNode.textContent; let nodeText = clonedParentNode.innerText || clonedParentNode.textContent;
if (!respectWhitespace) {
nodeText = nodeText.trim();
}
return nodeText;
} }
} }
   
Loading
Loading