You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@solr.apache.org by GitBox <gi...@apache.org> on 2021/10/24 16:59:04 UTC

[GitHub] [solr] sonatype-lift[bot] commented on a change in pull request #365: Move Antora work in progress from my fork to project repo

sonatype-lift[bot] commented on a change in pull request #365:
URL: https://github.com/apache/solr/pull/365#discussion_r735144298



##########
File path: solr/solr-ref-guide/ui/src/js/06-copy-to-clipboard.js
##########
@@ -0,0 +1,76 @@
+;(function () {
+  'use strict'
+
+  var CMD_RX = /^\$ (\S[^\\\n]*(\\\n(?!\$ )[^\\\n]*)*)(?=\n|$)/gm
+  var LINE_CONTINUATION_RX = /( ) *\\\n *|\\\n( ?) */g
+  var TRAILING_SPACE_RX = / +$/gm
+  var config = (document.getElementById('site-script') || { dataset: {} }).dataset
+
+  ;[].slice.call(document.querySelectorAll('.doc pre.highlight, .doc .literalblock pre')).forEach(function (pre) {
+    var code, language, lang, copy, toast, toolbox
+    if (pre.classList.contains('highlight')) {
+      code = pre.querySelector('code')
+      if ((language = code.dataset.lang) && language !== 'console') {
+        ;(lang = document.createElement('span')).className = 'source-lang'
+        lang.appendChild(document.createTextNode(language))
+      }
+    } else if (pre.innerText.startsWith('$ ')) {
+      var block = pre.parentNode.parentNode
+      block.classList.remove('literalblock')
+      block.classList.add('listingblock')
+      pre.classList.add('highlightjs', 'highlight')
+      ;(code = document.createElement('code')).className = 'language-console hljs'
+      code.dataset.lang = 'console'
+      code.appendChild(pre.firstChild)
+      pre.appendChild(code)
+    } else {
+      return
+    }
+    ;(toolbox = document.createElement('div')).className = 'source-toolbox'
+    if (lang) toolbox.appendChild(lang)
+    if (window.navigator.clipboard) {
+      ;(copy = document.createElement('button')).className = 'copy-button'
+      copy.setAttribute('title', 'Copy to clipboard')
+      if (config.svgAs === 'svg') {
+        var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+        svg.setAttribute('class', 'copy-icon')
+        var use = document.createElementNS('http://www.w3.org/2000/svg', 'use')
+        use.setAttribute('href', window.uiRootPath + '/img/octicons-16.svg#icon-clippy')
+        svg.appendChild(use)
+        copy.appendChild(svg)
+      } else {
+        var img = document.createElement('img')
+        img.src = window.uiRootPath + '/img/octicons-16.svg#view-clippy'
+        img.alt = 'copy icon'
+        img.className = 'copy-icon'
+        copy.appendChild(img)
+      }
+      ;(toast = document.createElement('span')).className = 'copy-toast'
+      toast.appendChild(document.createTextNode('Copied!'))
+      copy.appendChild(toast)
+      toolbox.appendChild(copy)
+    }
+    pre.appendChild(toolbox)
+    if (copy) copy.addEventListener('click', writeToClipboard.bind(copy, code))
+  })
+
+  function extractCommands (text) {
+    var cmds = []
+    var m
+    while ((m = CMD_RX.exec(text))) cmds.push(m[1].replace(LINE_CONTINUATION_RX, '$1$2'))
+    return cmds.join(' && ')
+  }
+
+  function writeToClipboard (code) {
+    var text = code.innerText.replace(TRAILING_SPACE_RX, '')
+    if (code.dataset.lang === 'console' && text.startsWith('$ ')) text = extractCommands(text)
+    window.navigator.clipboard.writeText(text).then(
+      function () {
+        this.classList.add('clicked')
+        this.offsetHeight // eslint-disable-line no-unused-expressions

Review comment:
       *JSC_USELESS_CODE:*  Suspicious code. The result of the 'getprop' operator is not being used.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/build-preview-pages.js
##########
@@ -0,0 +1,141 @@
+'use strict'
+
+// NOTE remove patch after upgrading from asciidoctor.js to @asciidoctor/core
+Error.call = (self, ...args) => {
+  const err = new Error(...args)
+  return Object.assign(self, { message: err.message, stack: err.stack })
+}
+
+const asciidoctor = require('asciidoctor.js')()
+const fs = require('fs-extra')
+const handlebars = require('handlebars')
+const merge = require('merge-stream')
+const ospath = require('path')
+const path = ospath.posix
+const requireFromString = require('require-from-string')
+const { Transform } = require('stream')
+const map = (transform = () => {}, flush = undefined) => new Transform({ objectMode: true, transform, flush })
+const vfs = require('vinyl-fs')
+const yaml = require('js-yaml')
+
+const ASCIIDOC_ATTRIBUTES = { experimental: '', icons: 'font', sectanchors: '', 'source-highlighter': 'highlight.js' }
+
+module.exports = (src, previewSrc, previewDest, sink = () => map()) => (done) =>
+  Promise.all([
+    loadSampleUiModel(previewSrc),
+    toPromise(
+      merge(compileLayouts(src), registerPartials(src), registerHelpers(src), copyImages(previewSrc, previewDest))
+    ),
+  ])
+    .then(([baseUiModel, { layouts }]) => [{ ...baseUiModel, env: process.env }, layouts])
+    .then(([baseUiModel, layouts]) =>
+      vfs
+        .src('**/*.adoc', { base: previewSrc, cwd: previewSrc })
+        .pipe(
+          map((file, enc, next) => {
+            const siteRootPath = path.relative(ospath.dirname(file.path), ospath.resolve(previewSrc))
+            const uiModel = { ...baseUiModel }
+            uiModel.page = { ...uiModel.page }
+            uiModel.siteRootPath = siteRootPath
+            uiModel.siteRootUrl = path.join(siteRootPath, 'index.html')
+            uiModel.uiRootPath = path.join(siteRootPath, '_')
+            if (file.stem === '404') {
+              uiModel.page = { layout: '404', title: 'Page Not Found' }
+            } else {
+              const doc = asciidoctor.load(file.contents, { safe: 'safe', attributes: ASCIIDOC_ATTRIBUTES })
+              uiModel.page.attributes = Object.entries(doc.getAttributes())
+                .filter(([name, val]) => name.startsWith('page-'))
+                .reduce((accum, [name, val]) => {
+                  accum[name.substr(5)] = val
+                  return accum
+                }, {})
+              uiModel.page.layout = doc.getAttribute('page-layout', 'default')
+              uiModel.page.title = doc.getDocumentTitle()
+              uiModel.page.contents = Buffer.from(doc.convert())
+            }
+            file.extname = '.html'
+            try {
+              file.contents = Buffer.from(layouts.get(uiModel.page.layout)(uiModel))
+              next(null, file)
+            } catch (e) {
+              next(transformHandlebarsError(e, uiModel.page.layout))
+            }
+          })
+        )
+        .pipe(vfs.dest(previewDest))
+        .on('error', done)
+        .pipe(sink())
+    )
+
+function loadSampleUiModel (src) {
+  return fs.readFile(ospath.join(src, 'ui-model.yml'), 'utf8').then((contents) => yaml.safeLoad(contents))
+}
+
+function registerPartials (src) {
+  return vfs.src('partials/*.hbs', { base: src, cwd: src }).pipe(
+    map((file, enc, next) => {
+      handlebars.registerPartial(file.stem, file.contents.toString())
+      next()
+    })
+  )
+}
+
+function registerHelpers (src) {
+  handlebars.registerHelper('resolvePage', resolvePage)
+  handlebars.registerHelper('resolvePageURL', resolvePageURL)
+  return vfs.src('helpers/*.js', { base: src, cwd: src }).pipe(
+    map((file, enc, next) => {
+      handlebars.registerHelper(file.stem, requireFromString(file.contents.toString()))
+      next()
+    })
+  )
+}
+
+function compileLayouts (src) {
+  const layouts = new Map()
+  return vfs.src('layouts/*.hbs', { base: src, cwd: src }).pipe(
+    map(
+      (file, enc, next) => {
+        const srcName = path.join(src, file.relative)
+        layouts.set(file.stem, handlebars.compile(file.contents.toString(), { preventIndent: true, srcName }))
+        next()
+      },
+      function (done) {
+        this.push({ layouts })

Review comment:
       *E043:*  Too many errors. (73% scanned).
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/build.js
##########
@@ -0,0 +1,134 @@
+'use strict'
+
+const autoprefixer = require('autoprefixer')
+const browserify = require('browserify')
+const buffer = require('vinyl-buffer')
+const concat = require('gulp-concat')
+const cssnano = require('cssnano')
+const fs = require('fs-extra')
+const imagemin = require('gulp-imagemin')
+const merge = require('merge-stream')
+const ospath = require('path')
+const path = ospath.posix
+const postcss = require('gulp-postcss')
+const postcssCalc = require('postcss-calc')
+const postcssImport = require('postcss-import')
+const postcssUrl = require('postcss-url')
+const postcssVar = require('postcss-custom-properties')
+const { Transform } = require('stream')
+const map = (transform) => new Transform({ objectMode: true, transform })
+const through = () => map((file, enc, next) => next(null, file))
+const uglify = require('gulp-uglify')
+const vfs = require('vinyl-fs')
+
+module.exports = (src, dest, preview) => () => {
+  const opts = { base: src, cwd: src }
+  const sourcemaps = preview || process.env.SOURCEMAPS === 'true'
+  const postcssPlugins = [
+    postcssImport,
+    (css, { messages, opts: { file } }) =>
+      Promise.all(
+        messages
+          .reduce((accum, { file: depPath, type }) => (type === 'dependency' ? accum.concat(depPath) : accum), [])
+          .map((importedPath) => fs.stat(importedPath).then(({ mtime }) => mtime))
+      ).then((mtimes) => {
+        const newestMtime = mtimes.reduce((max, curr) => (!max || curr > max ? curr : max), file.stat.mtime)
+        if (newestMtime > file.stat.mtime) file.stat.mtimeMs = +(file.stat.mtime = newestMtime)
+      }),
+    postcssUrl([
+      {
+        filter: '**/~typeface-*/files/*',
+        url: (asset) => {
+          const relpath = asset.pathname.substr(1)
+          const abspath = require.resolve(relpath)
+          const basename = ospath.basename(abspath)
+          const destpath = ospath.join(dest, 'font', basename)
+          if (!fs.pathExistsSync(destpath)) fs.copySync(abspath, destpath)
+          return path.join('..', 'font', basename)
+        },
+      },
+    ]),
+    postcssVar({ preserve: preview }),
+    preview ? postcssCalc : () => {},
+    autoprefixer,
+    preview
+      ? () => {}
+      : (css, result) => cssnano({ preset: 'default' })(css, result).then(() => postcssPseudoElementFixer(css, result)),
+  ]
+
+  return merge(
+    vfs
+      .src('js/+([0-9])-*.js', { ...opts, sourcemaps })
+      .pipe(uglify())
+      // NOTE concat already uses stat from newest combined file
+      .pipe(concat('js/site.js')),
+    vfs
+      .src('js/vendor/*([^.])?(.bundle).js', { ...opts, read: false })
+      .pipe(
+        // see https://gulpjs.org/recipes/browserify-multiple-destination.html
+        map((file, enc, next) => {
+          if (file.relative.endsWith('.bundle.js')) {
+            const mtimePromises = []
+            const bundlePath = file.path
+            browserify(file.relative, { basedir: src, detectGlobals: false })
+              .plugin('browser-pack-flat/plugin')
+              .on('file', (bundledPath) => {
+                if (bundledPath !== bundlePath) mtimePromises.push(fs.stat(bundledPath).then(({ mtime }) => mtime))
+              })
+              .bundle((bundleError, bundleBuffer) =>
+                Promise.all(mtimePromises).then((mtimes) => {
+                  const newestMtime = mtimes.reduce((max, curr) => (curr > max ? curr : max), file.stat.mtime)
+                  if (newestMtime > file.stat.mtime) file.stat.mtimeMs = +(file.stat.mtime = newestMtime)
+                  if (bundleBuffer !== undefined) file.contents = bundleBuffer
+                  file.path = file.path.slice(0, file.path.length - 10) + '.js'
+                  next(bundleError, file)
+                })
+              )
+          } else {
+            fs.readFile(file.path, 'UTF-8').then((contents) => {
+              file.contents = Buffer.from(contents)
+              next(null, file)
+            })
+          }
+        })
+      )
+      .pipe(buffer())
+      .pipe(uglify()),
+    vfs
+      .src('js/vendor/*.min.js', opts)
+      .pipe(map((file, enc, next) => next(null, Object.assign(file, { extname: '' }, { extname: '.js' })))),
+    // NOTE use this statement to bundle a JavaScript library that cannot be browserified, like jQuery
+    //vfs.src(require.resolve('<package-name-or-require-path>'), opts).pipe(concat('js/vendor/<library-name>.js')),
+    vfs
+      .src(['css/site.css', 'css/vendor/*.css'], { ...opts, sourcemaps })
+      .pipe(postcss((file) => ({ plugins: postcssPlugins, options: { file } }))),
+    vfs.src('font/*.{ttf,woff*(2)}', opts),
+    vfs.src('img/**/*.{gif,ico,jpg,png,svg}', opts).pipe(
+      preview
+        ? through()
+        : imagemin(
+          [
+            imagemin.gifsicle(),
+            imagemin.jpegtran(),
+            imagemin.optipng(),
+            imagemin.svgo({
+              plugins: [
+                { cleanupIDs: { preservePrefixes: ['icon-', 'view-'] } },
+                { removeViewBox: false },
+                { removeDesc: false },
+              ],
+            }),
+          ].reduce((accum, it) => (it ? accum.concat(it) : accum), [])
+        )
+    ),
+    vfs.src('helpers/*.js', opts),
+    vfs.src('layouts/*.hbs', opts),
+    vfs.src('partials/*.hbs', opts)
+  ).pipe(vfs.dest(dest, { sourcemaps: sourcemaps && '.' }))
+}
+
+function postcssPseudoElementFixer (css, result) {
+  css.walkRules(/(?:^|[^:]):(?:before|after)/, (rule) => {
+    rule.selector = rule.selectors.map((it) => it.replace(/(^|[^:]):(before|after)$/, '$1::$2')).join(',')

Review comment:
       *E043:*  Too many errors. (97% scanned).
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/01-nav.js
##########
@@ -0,0 +1,154 @@
+;(function () {
+  'use strict'
+
+  var SECT_CLASS_RX = /^sect(\d)$/
+
+  var navContainer = document.querySelector('.nav-container')
+  var navToggle = document.querySelector('.nav-toggle')
+
+  navToggle.addEventListener('click', showNav)
+  navContainer.addEventListener('click', trapEvent)
+
+  var menuPanel = navContainer.querySelector('[data-panel=menu]')
+  if (!menuPanel) return
+  var nav = navContainer.querySelector('.nav')
+
+  var currentPageItem = menuPanel.querySelector('.is-current-page')
+  var originalPageItem = currentPageItem
+  if (currentPageItem) {
+    activateCurrentPath(currentPageItem)
+    scrollItemToMidpoint(menuPanel, currentPageItem.querySelector('.nav-link'))
+  } else {
+    menuPanel.scrollTop = 0
+  }
+
+  find(menuPanel, '.nav-item-toggle').forEach(function (btn) {
+    var li = btn.parentElement
+    btn.addEventListener('click', toggleActive.bind(li))
+    var navItemSpan = findNextElement(btn, '.nav-text')
+    if (navItemSpan) {
+      navItemSpan.style.cursor = 'pointer'
+      navItemSpan.addEventListener('click', toggleActive.bind(li))
+    }
+  })
+
+  nav.querySelector('[data-panel=explore] .context').addEventListener('click', function () {
+    // NOTE logic assumes there are only two panels
+    find(nav, '[data-panel]').forEach(function (panel) {
+      panel.classList.toggle('is-active')
+    })
+  })
+
+  // NOTE prevent text from being selected by double click
+  menuPanel.addEventListener('mousedown', function (e) {
+    if (e.detail > 1) e.preventDefault()
+  })
+
+  function onHashChange () {
+    var navLink
+    var hash = window.location.hash
+    if (hash) {
+      if (hash.indexOf('%')) hash = decodeURIComponent(hash)
+      navLink = menuPanel.querySelector('.nav-link[href="' + hash + '"]')
+      if (!navLink) {
+        var targetNode = document.getElementById(hash.slice(1))
+        if (targetNode) {
+          var current = targetNode
+          var ceiling = document.querySelector('article.doc')
+          while ((current = current.parentNode) && current !== ceiling) {
+            var id = current.id
+            // NOTE: look for section heading
+            if (!id && (id = SECT_CLASS_RX.test(current.className))) id = (current.firstElementChild || {}).id
+            if (id && (navLink = menuPanel.querySelector('.nav-link[href="#' + id + '"]'))) break
+          }
+        }
+      }
+    }
+    var navItem
+    if (navLink) {
+      navItem = navLink.parentNode
+    } else if (originalPageItem) {
+      navLink = (navItem = originalPageItem).querySelector('.nav-link')
+    } else {
+      return
+    }
+    if (navItem === currentPageItem) return
+    find(menuPanel, '.nav-item.is-active').forEach(function (el) {
+      el.classList.remove('is-active', 'is-current-path', 'is-current-page')
+    })
+    navItem.classList.add('is-current-page')
+    currentPageItem = navItem
+    activateCurrentPath(navItem)
+    scrollItemToMidpoint(menuPanel, navLink)
+  }
+
+  if (menuPanel.querySelector('.nav-link[href^="#"]')) {
+    if (window.location.hash) onHashChange()
+    window.addEventListener('hashchange', onHashChange)
+  }
+
+  function activateCurrentPath (navItem) {
+    var ancestorClasses
+    var ancestor = navItem.parentNode

Review comment:
       *E043:*  Too many errors. (59% scanned).
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/02-on-this-page.js
##########
@@ -0,0 +1,114 @@
+;(function () {
+  'use strict'
+
+  var sidebar = document.querySelector('nav.toc.sidebar')
+  if (!sidebar) return
+  if (document.querySelector('body.-toc')) return sidebar.parentNode.removeChild(sidebar)
+  var levels = parseInt(sidebar.dataset.levels || 2, 10)
+  if (levels < 0) return
+
+  var articleSelector = 'article.doc'
+  var article = document.querySelector(articleSelector)
+  var headingsSelector = []
+  for (var level = 0; level <= levels; level++) {
+    var headingSelector = [articleSelector]
+    if (level) {
+      for (var l = 1; l <= level; l++) headingSelector.push((l === 2 ? '.sectionbody>' : '') + '.sect' + l)
+      headingSelector.push('h' + (level + 1) + '[id]')
+    } else {
+      headingSelector.push('h1[id].sect0')
+    }
+    headingsSelector.push(headingSelector.join('>'))
+  }
+  var headings = find(headingsSelector.join(','), article.parentNode)
+  if (!headings.length) return sidebar.parentNode.removeChild(sidebar)
+
+  var lastActiveFragment
+  var links = {}
+  var list = headings.reduce(function (accum, heading) {
+    var link = document.createElement('a')
+    link.textContent = heading.textContent
+    links[(link.href = '#' + heading.id)] = link
+    var listItem = document.createElement('li')
+    listItem.dataset.level = parseInt(heading.nodeName.slice(1), 10) - 1
+    listItem.appendChild(link)
+    accum.appendChild(listItem)
+    return accum
+  }, document.createElement('ul'))
+
+  var menu = sidebar.querySelector('.toc-menu')
+  if (!menu) (menu = document.createElement('div')).className = 'toc-menu'
+
+  var title = document.createElement('h3')
+  title.textContent = sidebar.dataset.title || 'Contents'
+  menu.appendChild(title)
+  menu.appendChild(list)
+
+  var startOfContent = !document.getElementById('toc') && article.querySelector('h1.page ~ :not(.is-before-toc)')
+  if (startOfContent) {
+    var embeddedToc = document.createElement('nav')
+    embeddedToc.className = 'toc embedded'
+    embeddedToc.appendChild(menu.cloneNode(true))
+    startOfContent.parentNode.insertBefore(embeddedToc, startOfContent)
+  }
+
+  window.addEventListener('load', function () {
+    onScroll()
+    window.addEventListener('scroll', onScroll)
+  })
+
+  function onScroll () {
+    var scrolledBy = window.pageYOffset
+    var buffer = getNumericStyleVal(document.documentElement, 'fontSize') * 1.15
+    var ceil = article.offsetTop
+    if (scrolledBy && window.innerHeight + scrolledBy + 2 >= document.documentElement.scrollHeight) {
+      lastActiveFragment = Array.isArray(lastActiveFragment) ? lastActiveFragment : Array(lastActiveFragment || 0)
+      var activeFragments = []
+      var lastIdx = headings.length - 1
+      headings.forEach(function (heading, idx) {
+        var fragment = '#' + heading.id
+        if (idx === lastIdx || heading.getBoundingClientRect().top + getNumericStyleVal(heading, 'paddingTop') > ceil) {
+          activeFragments.push(fragment)
+          if (lastActiveFragment.indexOf(fragment) < 0) links[fragment].classList.add('is-active')

Review comment:
       *E043:*  Too many errors. (62% scanned).
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/06-copy-to-clipboard.js
##########
@@ -0,0 +1,76 @@
+;(function () {
+  'use strict'
+
+  var CMD_RX = /^\$ (\S[^\\\n]*(\\\n(?!\$ )[^\\\n]*)*)(?=\n|$)/gm
+  var LINE_CONTINUATION_RX = /( ) *\\\n *|\\\n( ?) */g
+  var TRAILING_SPACE_RX = / +$/gm
+  var config = (document.getElementById('site-script') || { dataset: {} }).dataset
+
+  ;[].slice.call(document.querySelectorAll('.doc pre.highlight, .doc .literalblock pre')).forEach(function (pre) {
+    var code, language, lang, copy, toast, toolbox
+    if (pre.classList.contains('highlight')) {
+      code = pre.querySelector('code')
+      if ((language = code.dataset.lang) && language !== 'console') {
+        ;(lang = document.createElement('span')).className = 'source-lang'
+        lang.appendChild(document.createTextNode(language))
+      }
+    } else if (pre.innerText.startsWith('$ ')) {
+      var block = pre.parentNode.parentNode
+      block.classList.remove('literalblock')
+      block.classList.add('listingblock')
+      pre.classList.add('highlightjs', 'highlight')
+      ;(code = document.createElement('code')).className = 'language-console hljs'
+      code.dataset.lang = 'console'
+      code.appendChild(pre.firstChild)
+      pre.appendChild(code)
+    } else {
+      return
+    }
+    ;(toolbox = document.createElement('div')).className = 'source-toolbox'
+    if (lang) toolbox.appendChild(lang)
+    if (window.navigator.clipboard) {
+      ;(copy = document.createElement('button')).className = 'copy-button'
+      copy.setAttribute('title', 'Copy to clipboard')
+      if (config.svgAs === 'svg') {
+        var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+        svg.setAttribute('class', 'copy-icon')
+        var use = document.createElementNS('http://www.w3.org/2000/svg', 'use')
+        use.setAttribute('href', window.uiRootPath + '/img/octicons-16.svg#icon-clippy')
+        svg.appendChild(use)
+        copy.appendChild(svg)
+      } else {
+        var img = document.createElement('img')
+        img.src = window.uiRootPath + '/img/octicons-16.svg#view-clippy'
+        img.alt = 'copy icon'
+        img.className = 'copy-icon'
+        copy.appendChild(img)
+      }
+      ;(toast = document.createElement('span')).className = 'copy-toast'
+      toast.appendChild(document.createTextNode('Copied!'))
+      copy.appendChild(toast)
+      toolbox.appendChild(copy)
+    }
+    pre.appendChild(toolbox)
+    if (copy) copy.addEventListener('click', writeToClipboard.bind(copy, code))
+  })
+
+  function extractCommands (text) {
+    var cmds = []
+    var m
+    while ((m = CMD_RX.exec(text))) cmds.push(m[1].replace(LINE_CONTINUATION_RX, '$1$2'))
+    return cmds.join(' && ')
+  }
+
+  function writeToClipboard (code) {
+    var text = code.innerText.replace(TRAILING_SPACE_RX, '')
+    if (code.dataset.lang === 'console' && text.startsWith('$ ')) text = extractCommands(text)
+    window.navigator.clipboard.writeText(text).then(
+      function () {
+        this.classList.add('clicked')
+        this.offsetHeight // eslint-disable-line no-unused-expressions
+        this.classList.remove('clicked')
+      }.bind(this),
+      function () {}
+    )

Review comment:
       *E043:*  Too many errors. (96% scanned).
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/build.js
##########
@@ -0,0 +1,134 @@
+'use strict'
+
+const autoprefixer = require('autoprefixer')
+const browserify = require('browserify')
+const buffer = require('vinyl-buffer')
+const concat = require('gulp-concat')
+const cssnano = require('cssnano')
+const fs = require('fs-extra')
+const imagemin = require('gulp-imagemin')
+const merge = require('merge-stream')
+const ospath = require('path')
+const path = ospath.posix
+const postcss = require('gulp-postcss')
+const postcssCalc = require('postcss-calc')
+const postcssImport = require('postcss-import')
+const postcssUrl = require('postcss-url')
+const postcssVar = require('postcss-custom-properties')
+const { Transform } = require('stream')
+const map = (transform) => new Transform({ objectMode: true, transform })
+const through = () => map((file, enc, next) => next(null, file))
+const uglify = require('gulp-uglify')
+const vfs = require('vinyl-fs')
+
+module.exports = (src, dest, preview) => () => {
+  const opts = { base: src, cwd: src }
+  const sourcemaps = preview || process.env.SOURCEMAPS === 'true'
+  const postcssPlugins = [
+    postcssImport,
+    (css, { messages, opts: { file } }) =>
+      Promise.all(
+        messages
+          .reduce((accum, { file: depPath, type }) => (type === 'dependency' ? accum.concat(depPath) : accum), [])
+          .map((importedPath) => fs.stat(importedPath).then(({ mtime }) => mtime))
+      ).then((mtimes) => {
+        const newestMtime = mtimes.reduce((max, curr) => (!max || curr > max ? curr : max), file.stat.mtime)
+        if (newestMtime > file.stat.mtime) file.stat.mtimeMs = +(file.stat.mtime = newestMtime)
+      }),
+    postcssUrl([
+      {
+        filter: '**/~typeface-*/files/*',
+        url: (asset) => {
+          const relpath = asset.pathname.substr(1)
+          const abspath = require.resolve(relpath)
+          const basename = ospath.basename(abspath)
+          const destpath = ospath.join(dest, 'font', basename)
+          if (!fs.pathExistsSync(destpath)) fs.copySync(abspath, destpath)
+          return path.join('..', 'font', basename)
+        },
+      },
+    ]),
+    postcssVar({ preserve: preview }),
+    preview ? postcssCalc : () => {},
+    autoprefixer,
+    preview
+      ? () => {}
+      : (css, result) => cssnano({ preset: 'default' })(css, result).then(() => postcssPseudoElementFixer(css, result)),
+  ]
+
+  return merge(
+    vfs
+      .src('js/+([0-9])-*.js', { ...opts, sourcemaps })
+      .pipe(uglify())
+      // NOTE concat already uses stat from newest combined file
+      .pipe(concat('js/site.js')),
+    vfs
+      .src('js/vendor/*([^.])?(.bundle).js', { ...opts, read: false })
+      .pipe(
+        // see https://gulpjs.org/recipes/browserify-multiple-destination.html
+        map((file, enc, next) => {
+          if (file.relative.endsWith('.bundle.js')) {
+            const mtimePromises = []
+            const bundlePath = file.path
+            browserify(file.relative, { basedir: src, detectGlobals: false })
+              .plugin('browser-pack-flat/plugin')
+              .on('file', (bundledPath) => {
+                if (bundledPath !== bundlePath) mtimePromises.push(fs.stat(bundledPath).then(({ mtime }) => mtime))
+              })
+              .bundle((bundleError, bundleBuffer) =>
+                Promise.all(mtimePromises).then((mtimes) => {
+                  const newestMtime = mtimes.reduce((max, curr) => (curr > max ? curr : max), file.stat.mtime)
+                  if (newestMtime > file.stat.mtime) file.stat.mtimeMs = +(file.stat.mtime = newestMtime)
+                  if (bundleBuffer !== undefined) file.contents = bundleBuffer
+                  file.path = file.path.slice(0, file.path.length - 10) + '.js'
+                  next(bundleError, file)
+                })
+              )
+          } else {
+            fs.readFile(file.path, 'UTF-8').then((contents) => {
+              file.contents = Buffer.from(contents)
+              next(null, file)
+            })
+          }
+        })
+      )
+      .pipe(buffer())
+      .pipe(uglify()),
+    vfs
+      .src('js/vendor/*.min.js', opts)
+      .pipe(map((file, enc, next) => next(null, Object.assign(file, { extname: '' }, { extname: '.js' })))),
+    // NOTE use this statement to bundle a JavaScript library that cannot be browserified, like jQuery
+    //vfs.src(require.resolve('<package-name-or-require-path>'), opts).pipe(concat('js/vendor/<library-name>.js')),
+    vfs
+      .src(['css/site.css', 'css/vendor/*.css'], { ...opts, sourcemaps })
+      .pipe(postcss((file) => ({ plugins: postcssPlugins, options: { file } }))),
+    vfs.src('font/*.{ttf,woff*(2)}', opts),
+    vfs.src('img/**/*.{gif,ico,jpg,png,svg}', opts).pipe(
+      preview
+        ? through()

Review comment:
       *W014:*  Misleading line break before '?'; readers may interpret this as an expression boundary.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/helpers/relativize.js
##########
@@ -0,0 +1,24 @@
+'use strict'
+
+const { posix: path } = require('path')
+
+module.exports = (to, from, ctx) => {
+  if (!to) return '#'
+  // NOTE only legacy invocation provides both to and from
+  if (!ctx) from = (ctx = from).data.root.page.url
+  if (to.charAt() !== '/') return to
+  if (!from) return (ctx.data.root.site.path || '') + to
+  let hash = ''
+  const hashIdx = to.indexOf('#')
+  if (~hashIdx) {
+    hash = to.substr(hashIdx)
+    to = to.substr(0, hashIdx)
+  }
+  return to === from
+    ? hash || (isDir(to) ? './' : path.basename(to))

Review comment:
       *W014:*  Misleading line break before '?'; readers may interpret this as an expression boundary.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/06-copy-to-clipboard.js
##########
@@ -0,0 +1,76 @@
+;(function () {
+  'use strict'
+
+  var CMD_RX = /^\$ (\S[^\\\n]*(\\\n(?!\$ )[^\\\n]*)*)(?=\n|$)/gm
+  var LINE_CONTINUATION_RX = /( ) *\\\n *|\\\n( ?) */g
+  var TRAILING_SPACE_RX = / +$/gm
+  var config = (document.getElementById('site-script') || { dataset: {} }).dataset
+
+  ;[].slice.call(document.querySelectorAll('.doc pre.highlight, .doc .literalblock pre')).forEach(function (pre) {
+    var code, language, lang, copy, toast, toolbox
+    if (pre.classList.contains('highlight')) {
+      code = pre.querySelector('code')
+      if ((language = code.dataset.lang) && language !== 'console') {
+        ;(lang = document.createElement('span')).className = 'source-lang'
+        lang.appendChild(document.createTextNode(language))
+      }
+    } else if (pre.innerText.startsWith('$ ')) {
+      var block = pre.parentNode.parentNode
+      block.classList.remove('literalblock')
+      block.classList.add('listingblock')
+      pre.classList.add('highlightjs', 'highlight')
+      ;(code = document.createElement('code')).className = 'language-console hljs'
+      code.dataset.lang = 'console'
+      code.appendChild(pre.firstChild)
+      pre.appendChild(code)
+    } else {
+      return
+    }
+    ;(toolbox = document.createElement('div')).className = 'source-toolbox'
+    if (lang) toolbox.appendChild(lang)
+    if (window.navigator.clipboard) {
+      ;(copy = document.createElement('button')).className = 'copy-button'
+      copy.setAttribute('title', 'Copy to clipboard')
+      if (config.svgAs === 'svg') {
+        var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+        svg.setAttribute('class', 'copy-icon')
+        var use = document.createElementNS('http://www.w3.org/2000/svg', 'use')
+        use.setAttribute('href', window.uiRootPath + '/img/octicons-16.svg#icon-clippy')
+        svg.appendChild(use)
+        copy.appendChild(svg)
+      } else {
+        var img = document.createElement('img')
+        img.src = window.uiRootPath + '/img/octicons-16.svg#view-clippy'
+        img.alt = 'copy icon'
+        img.className = 'copy-icon'
+        copy.appendChild(img)
+      }
+      ;(toast = document.createElement('span')).className = 'copy-toast'
+      toast.appendChild(document.createTextNode('Copied!'))
+      copy.appendChild(toast)
+      toolbox.appendChild(copy)
+    }
+    pre.appendChild(toolbox)
+    if (copy) copy.addEventListener('click', writeToClipboard.bind(copy, code))
+  })
+
+  function extractCommands (text) {
+    var cmds = []
+    var m
+    while ((m = CMD_RX.exec(text))) cmds.push(m[1].replace(LINE_CONTINUATION_RX, '$1$2'))
+    return cmds.join(' && ')
+  }
+
+  function writeToClipboard (code) {
+    var text = code.innerText.replace(TRAILING_SPACE_RX, '')
+    if (code.dataset.lang === 'console' && text.startsWith('$ ')) text = extractCommands(text)
+    window.navigator.clipboard.writeText(text).then(
+      function () {
+        this.classList.add('clicked')
+        this.offsetHeight // eslint-disable-line no-unused-expressions

Review comment:
       *W030:*  Expected an assignment or function call and instead saw an expression.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/build-preview-pages.js
##########
@@ -0,0 +1,141 @@
+'use strict'
+
+// NOTE remove patch after upgrading from asciidoctor.js to @asciidoctor/core
+Error.call = (self, ...args) => {
+  const err = new Error(...args)
+  return Object.assign(self, { message: err.message, stack: err.stack })
+}
+
+const asciidoctor = require('asciidoctor.js')()
+const fs = require('fs-extra')
+const handlebars = require('handlebars')
+const merge = require('merge-stream')
+const ospath = require('path')
+const path = ospath.posix
+const requireFromString = require('require-from-string')
+const { Transform } = require('stream')
+const map = (transform = () => {}, flush = undefined) => new Transform({ objectMode: true, transform, flush })
+const vfs = require('vinyl-fs')
+const yaml = require('js-yaml')
+
+const ASCIIDOC_ATTRIBUTES = { experimental: '', icons: 'font', sectanchors: '', 'source-highlighter': 'highlight.js' }
+
+module.exports = (src, previewSrc, previewDest, sink = () => map()) => (done) =>
+  Promise.all([
+    loadSampleUiModel(previewSrc),
+    toPromise(
+      merge(compileLayouts(src), registerPartials(src), registerHelpers(src), copyImages(previewSrc, previewDest))
+    ),
+  ])
+    .then(([baseUiModel, { layouts }]) => [{ ...baseUiModel, env: process.env }, layouts])
+    .then(([baseUiModel, layouts]) =>
+      vfs
+        .src('**/*.adoc', { base: previewSrc, cwd: previewSrc })
+        .pipe(
+          map((file, enc, next) => {
+            const siteRootPath = path.relative(ospath.dirname(file.path), ospath.resolve(previewSrc))
+            const uiModel = { ...baseUiModel }
+            uiModel.page = { ...uiModel.page }
+            uiModel.siteRootPath = siteRootPath
+            uiModel.siteRootUrl = path.join(siteRootPath, 'index.html')
+            uiModel.uiRootPath = path.join(siteRootPath, '_')
+            if (file.stem === '404') {
+              uiModel.page = { layout: '404', title: 'Page Not Found' }
+            } else {
+              const doc = asciidoctor.load(file.contents, { safe: 'safe', attributes: ASCIIDOC_ATTRIBUTES })
+              uiModel.page.attributes = Object.entries(doc.getAttributes())
+                .filter(([name, val]) => name.startsWith('page-'))
+                .reduce((accum, [name, val]) => {
+                  accum[name.substr(5)] = val
+                  return accum
+                }, {})
+              uiModel.page.layout = doc.getAttribute('page-layout', 'default')
+              uiModel.page.title = doc.getDocumentTitle()
+              uiModel.page.contents = Buffer.from(doc.convert())
+            }
+            file.extname = '.html'
+            try {
+              file.contents = Buffer.from(layouts.get(uiModel.page.layout)(uiModel))
+              next(null, file)
+            } catch (e) {
+              next(transformHandlebarsError(e, uiModel.page.layout))
+            }
+          })
+        )
+        .pipe(vfs.dest(previewDest))
+        .on('error', done)
+        .pipe(sink())
+    )
+
+function loadSampleUiModel (src) {
+  return fs.readFile(ospath.join(src, 'ui-model.yml'), 'utf8').then((contents) => yaml.safeLoad(contents))
+}
+
+function registerPartials (src) {
+  return vfs.src('partials/*.hbs', { base: src, cwd: src }).pipe(
+    map((file, enc, next) => {
+      handlebars.registerPartial(file.stem, file.contents.toString())
+      next()
+    })
+  )
+}
+
+function registerHelpers (src) {
+  handlebars.registerHelper('resolvePage', resolvePage)
+  handlebars.registerHelper('resolvePageURL', resolvePageURL)
+  return vfs.src('helpers/*.js', { base: src, cwd: src }).pipe(
+    map((file, enc, next) => {
+      handlebars.registerHelper(file.stem, requireFromString(file.contents.toString()))
+      next()
+    })
+  )
+}
+
+function compileLayouts (src) {
+  const layouts = new Map()
+  return vfs.src('layouts/*.hbs', { base: src, cwd: src }).pipe(
+    map(
+      (file, enc, next) => {
+        const srcName = path.join(src, file.relative)
+        layouts.set(file.stem, handlebars.compile(file.contents.toString(), { preventIndent: true, srcName }))
+        next()
+      },
+      function (done) {
+        this.push({ layouts })

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/build.js
##########
@@ -0,0 +1,134 @@
+'use strict'
+
+const autoprefixer = require('autoprefixer')
+const browserify = require('browserify')
+const buffer = require('vinyl-buffer')
+const concat = require('gulp-concat')
+const cssnano = require('cssnano')
+const fs = require('fs-extra')
+const imagemin = require('gulp-imagemin')
+const merge = require('merge-stream')
+const ospath = require('path')
+const path = ospath.posix
+const postcss = require('gulp-postcss')
+const postcssCalc = require('postcss-calc')
+const postcssImport = require('postcss-import')
+const postcssUrl = require('postcss-url')
+const postcssVar = require('postcss-custom-properties')
+const { Transform } = require('stream')
+const map = (transform) => new Transform({ objectMode: true, transform })
+const through = () => map((file, enc, next) => next(null, file))
+const uglify = require('gulp-uglify')
+const vfs = require('vinyl-fs')
+
+module.exports = (src, dest, preview) => () => {
+  const opts = { base: src, cwd: src }
+  const sourcemaps = preview || process.env.SOURCEMAPS === 'true'
+  const postcssPlugins = [
+    postcssImport,
+    (css, { messages, opts: { file } }) =>
+      Promise.all(
+        messages
+          .reduce((accum, { file: depPath, type }) => (type === 'dependency' ? accum.concat(depPath) : accum), [])
+          .map((importedPath) => fs.stat(importedPath).then(({ mtime }) => mtime))
+      ).then((mtimes) => {
+        const newestMtime = mtimes.reduce((max, curr) => (!max || curr > max ? curr : max), file.stat.mtime)
+        if (newestMtime > file.stat.mtime) file.stat.mtimeMs = +(file.stat.mtime = newestMtime)
+      }),
+    postcssUrl([
+      {
+        filter: '**/~typeface-*/files/*',
+        url: (asset) => {
+          const relpath = asset.pathname.substr(1)
+          const abspath = require.resolve(relpath)
+          const basename = ospath.basename(abspath)
+          const destpath = ospath.join(dest, 'font', basename)
+          if (!fs.pathExistsSync(destpath)) fs.copySync(abspath, destpath)
+          return path.join('..', 'font', basename)
+        },
+      },
+    ]),
+    postcssVar({ preserve: preview }),
+    preview ? postcssCalc : () => {},
+    autoprefixer,
+    preview
+      ? () => {}
+      : (css, result) => cssnano({ preset: 'default' })(css, result).then(() => postcssPseudoElementFixer(css, result)),
+  ]
+
+  return merge(
+    vfs
+      .src('js/+([0-9])-*.js', { ...opts, sourcemaps })
+      .pipe(uglify())
+      // NOTE concat already uses stat from newest combined file
+      .pipe(concat('js/site.js')),
+    vfs
+      .src('js/vendor/*([^.])?(.bundle).js', { ...opts, read: false })
+      .pipe(
+        // see https://gulpjs.org/recipes/browserify-multiple-destination.html
+        map((file, enc, next) => {
+          if (file.relative.endsWith('.bundle.js')) {
+            const mtimePromises = []
+            const bundlePath = file.path
+            browserify(file.relative, { basedir: src, detectGlobals: false })
+              .plugin('browser-pack-flat/plugin')
+              .on('file', (bundledPath) => {
+                if (bundledPath !== bundlePath) mtimePromises.push(fs.stat(bundledPath).then(({ mtime }) => mtime))
+              })
+              .bundle((bundleError, bundleBuffer) =>
+                Promise.all(mtimePromises).then((mtimes) => {
+                  const newestMtime = mtimes.reduce((max, curr) => (curr > max ? curr : max), file.stat.mtime)
+                  if (newestMtime > file.stat.mtime) file.stat.mtimeMs = +(file.stat.mtime = newestMtime)
+                  if (bundleBuffer !== undefined) file.contents = bundleBuffer
+                  file.path = file.path.slice(0, file.path.length - 10) + '.js'
+                  next(bundleError, file)
+                })
+              )
+          } else {
+            fs.readFile(file.path, 'UTF-8').then((contents) => {
+              file.contents = Buffer.from(contents)
+              next(null, file)
+            })
+          }
+        })
+      )
+      .pipe(buffer())
+      .pipe(uglify()),
+    vfs
+      .src('js/vendor/*.min.js', opts)
+      .pipe(map((file, enc, next) => next(null, Object.assign(file, { extname: '' }, { extname: '.js' })))),
+    // NOTE use this statement to bundle a JavaScript library that cannot be browserified, like jQuery
+    //vfs.src(require.resolve('<package-name-or-require-path>'), opts).pipe(concat('js/vendor/<library-name>.js')),
+    vfs
+      .src(['css/site.css', 'css/vendor/*.css'], { ...opts, sourcemaps })
+      .pipe(postcss((file) => ({ plugins: postcssPlugins, options: { file } }))),
+    vfs.src('font/*.{ttf,woff*(2)}', opts),
+    vfs.src('img/**/*.{gif,ico,jpg,png,svg}', opts).pipe(
+      preview
+        ? through()
+        : imagemin(
+          [
+            imagemin.gifsicle(),
+            imagemin.jpegtran(),
+            imagemin.optipng(),
+            imagemin.svgo({
+              plugins: [
+                { cleanupIDs: { preservePrefixes: ['icon-', 'view-'] } },
+                { removeViewBox: false },
+                { removeDesc: false },
+              ],
+            }),
+          ].reduce((accum, it) => (it ? accum.concat(it) : accum), [])
+        )
+    ),
+    vfs.src('helpers/*.js', opts),
+    vfs.src('layouts/*.hbs', opts),
+    vfs.src('partials/*.hbs', opts)
+  ).pipe(vfs.dest(dest, { sourcemaps: sourcemaps && '.' }))
+}
+
+function postcssPseudoElementFixer (css, result) {
+  css.walkRules(/(?:^|[^:]):(?:before|after)/, (rule) => {
+    rule.selector = rule.selectors.map((it) => it.replace(/(^|[^:]):(before|after)$/, '$1::$2')).join(',')

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/format.js
##########
@@ -0,0 +1,10 @@
+'use strict'
+
+const prettier = require('../tools/gulp-prettier-eslint')
+const vfs = require('vinyl-fs')
+
+module.exports = (files) => () =>
+  vfs
+    .src(files)
+    .pipe(prettier())
+    .pipe(vfs.dest((file) => file.base))

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/index.js
##########
@@ -0,0 +1,5 @@
+'use strict'
+
+const camelCase = (name) => name.replace(/[-]./g, (m) => m.substr(1).toUpperCase())
+
+module.exports = require('require-directory')(module, __dirname, { recurse: false, rename: camelCase })

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/lint-css.js
##########
@@ -0,0 +1,10 @@
+'use strict'
+
+const stylelint = require('gulp-stylelint')
+const vfs = require('vinyl-fs')
+
+module.exports = (files) => (done) =>
+  vfs
+    .src(files)
+    .pipe(stylelint({ reporters: [{ formatter: 'string', console: true }], failAfterError: true }))
+    .on('error', done)

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/lint-js.js
##########
@@ -0,0 +1,12 @@
+'use strict'
+
+const eslint = require('gulp-eslint')
+const vfs = require('vinyl-fs')
+
+module.exports = (files) => (done) =>
+  vfs
+    .src(files)
+    .pipe(eslint())
+    .pipe(eslint.format())
+    .pipe(eslint.failAfterError())
+    .on('error', done)

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/pack.js
##########
@@ -0,0 +1,11 @@
+'use strict'
+
+const vfs = require('vinyl-fs')
+const zip = require('gulp-vinyl-zip')
+const path = require('path')
+
+module.exports = (src, dest, bundleName, onFinish) => () =>
+  vfs
+    .src('**/*', { base: src, cwd: src })
+    .pipe(zip.dest(path.join(dest, `${bundleName}-bundle.zip`)))
+    .on('finish', () => onFinish && onFinish(path.resolve(dest, `${bundleName}-bundle.zip`)))

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/remove.js
##########
@@ -0,0 +1,9 @@
+'use strict'
+
+const fs = require('fs-extra')
+const { Transform } = require('stream')
+const map = (transform) => new Transform({ objectMode: true, transform })
+const vfs = require('vinyl-fs')
+
+module.exports = (files) => () =>
+  vfs.src(files, { allowEmpty: true }).pipe(map((file, enc, next) => fs.remove(file.path, next)))

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tasks/serve.js
##########
@@ -0,0 +1,36 @@
+'use strict'
+
+const connect = require('gulp-connect')
+const os = require('os')
+
+const ANY_HOST = '0.0.0.0'
+const URL_RX = /(https?):\/\/(?:[^/: ]+)(:\d+)?/
+
+module.exports = (root, opts = {}, watch = undefined) => (done) => {
+  connect.server({ ...opts, middleware: opts.host === ANY_HOST ? decorateLog : undefined, root }, function () {
+    this.server.on('close', done)
+    if (watch) watch()
+  })
+}
+
+function decorateLog (_, app) {
+  const _log = app.log
+  app.log = (msg) => {
+    if (msg.startsWith('Server started ')) {
+      const localIp = getLocalIp()
+      const replacement = '$1://localhost$2' + (localIp ? ` and $1://${localIp}$2` : '')
+      msg = msg.replace(URL_RX, replacement)
+    }
+    _log(msg)
+  }
+  return []
+}
+
+function getLocalIp () {
+  for (const records of Object.values(os.networkInterfaces())) {
+    for (const record of records) {
+      if (!record.internal && record.family === 'IPv4') return record.address
+    }
+  }
+  return 'localhost'

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tools/create-task.js
##########
@@ -0,0 +1,24 @@
+'use strict'
+
+const metadata = require('undertaker/lib/helpers/metadata')
+const { watch } = require('gulp')
+
+module.exports = ({ name, desc, opts, call: fn, loop }) => {
+  if (name) {
+    const displayName = fn.displayName
+    if (displayName === '<series>' || displayName === '<parallel>') {
+      metadata.get(fn).tree.label = `${displayName} ${name}`
+    }
+    fn.displayName = name
+  }
+  if (loop) {
+    const delegate = fn
+    name = delegate.displayName
+    delegate.displayName = `${name}:loop`
+    fn = () => watch(loop, { ignoreInitial: false }, delegate)
+    fn.displayName = name
+  }
+  if (desc) fn.description = desc
+  if (opts) fn.flags = opts
+  return fn
+}

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tools/export-tasks.js
##########
@@ -0,0 +1,14 @@
+'use strict'
+
+module.exports = (...tasks) => {
+  const seed = {}
+  if (tasks.length) {
+    if (tasks.lastIndexOf(tasks[0]) > 0) {
+      const task1 = tasks.shift()
+      seed.default = Object.assign(task1.bind(null), { description: `=> ${task1.displayName}`, displayName: 'default' })
+    }
+    return tasks.reduce((acc, it) => (acc[it.displayName || it.name] = it) && acc, seed)
+  } else {
+    return seed
+  }
+}

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulp.d/tools/gulp-prettier-eslint.js
##########
@@ -0,0 +1,44 @@
+'use strict'
+
+const log = require('fancy-log')
+const PluginError = require('plugin-error')
+const prettierEslint = require('prettier-eslint')
+const { Transform } = require('stream')
+const map = (transform) => new Transform({ objectMode: true, transform })
+
+module.exports = () => {
+  const report = { changed: 0, unchanged: 0 }
+  return map(format).on('finish', () => {
+    if (report.changed > 0) {
+      const changed = 'formatted '
+        .concat(report.changed)
+        .concat(' file')
+        .concat(report.changed === 1 ? '' : 's')
+      const unchanged = 'left '
+        .concat(report.unchanged)
+        .concat(' file')
+        .concat(report.unchanged === 1 ? '' : 's')
+        .concat(' unchanged')
+      log(`prettier-eslint: ${changed}; ${unchanged}`)
+    } else {
+      log(`prettier-eslint: left ${report.unchanged} file${report.unchanged === 1 ? '' : 's'} unchanged`)
+    }
+  })
+
+  function format (file, enc, next) {
+    if (file.isNull()) return next()
+    if (file.isStream()) return next(new PluginError('gulp-prettier-eslint', 'Streaming not supported'))
+
+    const input = file.contents.toString()
+    const output = prettierEslint({ text: input, filePath: file.path })
+
+    if (input === output) {
+      report.unchanged += 1
+    } else {
+      report.changed += 1
+      file.contents = Buffer.from(output)
+    }
+
+    next(null, file)
+  }
+}

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/gulpfile.js
##########
@@ -0,0 +1,125 @@
+'use strict'
+
+const { parallel, series, watch } = require('gulp')
+const createTask = require('./gulp.d/tools/create-task')
+const exportTasks = require('./gulp.d/tools/export-tasks')
+const log = require('fancy-log')
+
+const bundleName = 'ui'
+const buildDir = 'build'
+const previewSrcDir = 'preview-src'
+const previewDestDir = 'public'
+const srcDir = 'src'
+const destDir = `${previewDestDir}/_`
+const { reload: livereload } = process.env.LIVERELOAD === 'true' ? require('gulp-connect') : {}
+const serverConfig = { host: '0.0.0.0', port: 5252, livereload }
+
+const task = require('./gulp.d/tasks')
+const glob = {
+  all: [srcDir, previewSrcDir],
+  css: `${srcDir}/css/**/*.css`,
+  js: ['gulpfile.js', 'gulp.d/**/*.js', `${srcDir}/{helpers,js}/**/*.js`],
+}
+
+const cleanTask = createTask({
+  name: 'clean',
+  desc: 'Clean files and folders generated by build',
+  call: task.remove(['build', 'public']),
+})
+
+const lintCssTask = createTask({
+  name: 'lint:css',
+  desc: 'Lint the CSS source files using stylelint (standard config)',
+  call: task.lintCss(glob.css),
+})
+
+const lintJsTask = createTask({
+  name: 'lint:js',
+  desc: 'Lint the JavaScript source files using eslint (JavaScript Standard Style)',
+  call: task.lintJs(glob.js),
+})
+
+const lintTask = createTask({
+  name: 'lint',
+  desc: 'Lint the CSS and JavaScript source files',
+  call: parallel(lintCssTask, lintJsTask),
+})
+
+const formatTask = createTask({
+  name: 'format',
+  desc: 'Format the JavaScript source files using prettify (JavaScript Standard Style)',
+  call: task.format(glob.js),
+})
+
+const buildTask = createTask({
+  name: 'build',
+  desc: 'Build and stage the UI assets for bundling',
+  call: task.build(
+    srcDir,
+    destDir,
+    process.argv.slice(2).some((name) => name.startsWith('preview'))
+  ),
+})
+
+const bundleBuildTask = createTask({
+  name: 'bundle:build',
+  call: series(cleanTask, lintTask, buildTask),
+})
+
+const bundlePackTask = createTask({
+  name: 'bundle:pack',
+  desc: 'Create a bundle of the staged UI assets for publishing',
+  call: task.pack(
+    destDir,
+    buildDir,
+    bundleName,
+    (bundlePath) => !process.env.CI && log(`Antora option: --ui-bundle-url=${bundlePath}`)
+  ),
+})
+
+const bundleTask = createTask({
+  name: 'bundle',
+  desc: 'Clean, lint, build, and bundle the UI for publishing',
+  call: series(bundleBuildTask, bundlePackTask),
+})
+
+const packTask = createTask({
+  name: 'pack',
+  desc: '(deprecated; use bundle instead)',
+  call: series(bundleTask),
+})
+
+const buildPreviewPagesTask = createTask({
+  name: 'preview:build-pages',
+  call: task.buildPreviewPages(srcDir, previewSrcDir, previewDestDir, livereload),
+})
+
+const previewBuildTask = createTask({
+  name: 'preview:build',
+  desc: 'Process and stage the UI assets and generate pages for the preview',
+  call: parallel(buildTask, buildPreviewPagesTask),
+})
+
+const previewServeTask = createTask({
+  name: 'preview:serve',
+  call: task.serve(previewDestDir, serverConfig, () => watch(glob.all, previewBuildTask)),
+})
+
+const previewTask = createTask({
+  name: 'preview',
+  desc: 'Generate a preview site and launch a server to view it',
+  call: series(previewBuildTask, previewServeTask),
+})
+
+module.exports = exportTasks(
+  bundleTask,
+  cleanTask,
+  lintTask,
+  formatTask,
+  buildTask,
+  bundleTask,
+  bundlePackTask,
+  previewTask,
+  previewBuildTask,
+  packTask
+)

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/index.js
##########
@@ -0,0 +1,4 @@
+'use strict'

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/helpers/and.js
##########
@@ -0,0 +1,9 @@
+'use strict'
+
+module.exports = (...args) => {
+  const numArgs = args.length
+  if (numArgs === 3) return args[0] && args[1]
+  if (numArgs < 3) throw new Error('{{and}} helper expects at least 2 arguments')
+  args.pop()
+  return args.every((it) => it)
+}

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/helpers/detag.js
##########
@@ -0,0 +1,5 @@
+'use strict'
+
+const TAG_ALL_RX = /<[^>]+>/g
+
+module.exports = (html) => html && html.replace(TAG_ALL_RX, '')

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/helpers/eq.js
##########
@@ -0,0 +1,3 @@
+'use strict'
+
+module.exports = (a, b) => a === b

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/helpers/increment.js
##########
@@ -0,0 +1,3 @@
+'use strict'
+
+module.exports = (value) => (value || 0) + 1

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/helpers/ne.js
##########
@@ -0,0 +1,3 @@
+'use strict'
+
+module.exports = (a, b) => a !== b

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/helpers/not.js
##########
@@ -0,0 +1,3 @@
+'use strict'
+
+module.exports = (val) => !val

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/helpers/or.js
##########
@@ -0,0 +1,9 @@
+'use strict'
+
+module.exports = (...args) => {
+  const numArgs = args.length
+  if (numArgs === 3) return args[0] || args[1]
+  if (numArgs < 3) throw new Error('{{or}} helper expects at least 2 arguments')
+  args.pop()
+  return args.some((it) => it)
+}

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/helpers/relativize.js
##########
@@ -0,0 +1,24 @@
+'use strict'
+
+const { posix: path } = require('path')
+
+module.exports = (to, from, ctx) => {
+  if (!to) return '#'
+  // NOTE only legacy invocation provides both to and from
+  if (!ctx) from = (ctx = from).data.root.page.url
+  if (to.charAt() !== '/') return to
+  if (!from) return (ctx.data.root.site.path || '') + to
+  let hash = ''
+  const hashIdx = to.indexOf('#')
+  if (~hashIdx) {
+    hash = to.substr(hashIdx)
+    to = to.substr(0, hashIdx)
+  }
+  return to === from
+    ? hash || (isDir(to) ? './' : path.basename(to))
+    : (path.relative(path.dirname(from + '.'), to) || '.') + (isDir(to) ? '/' + hash : hash)
+}
+
+function isDir (str) {
+  return str.charAt(str.length - 1) === '/'

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/helpers/year.js
##########
@@ -0,0 +1,3 @@
+'use strict'
+
+module.exports = () => new Date().getFullYear().toString()

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/01-nav.js
##########
@@ -0,0 +1,154 @@
+;(function () {
+  'use strict'
+
+  var SECT_CLASS_RX = /^sect(\d)$/
+
+  var navContainer = document.querySelector('.nav-container')
+  var navToggle = document.querySelector('.nav-toggle')
+
+  navToggle.addEventListener('click', showNav)
+  navContainer.addEventListener('click', trapEvent)
+
+  var menuPanel = navContainer.querySelector('[data-panel=menu]')
+  if (!menuPanel) return
+  var nav = navContainer.querySelector('.nav')
+
+  var currentPageItem = menuPanel.querySelector('.is-current-page')
+  var originalPageItem = currentPageItem
+  if (currentPageItem) {
+    activateCurrentPath(currentPageItem)
+    scrollItemToMidpoint(menuPanel, currentPageItem.querySelector('.nav-link'))
+  } else {
+    menuPanel.scrollTop = 0
+  }
+
+  find(menuPanel, '.nav-item-toggle').forEach(function (btn) {
+    var li = btn.parentElement
+    btn.addEventListener('click', toggleActive.bind(li))
+    var navItemSpan = findNextElement(btn, '.nav-text')
+    if (navItemSpan) {
+      navItemSpan.style.cursor = 'pointer'
+      navItemSpan.addEventListener('click', toggleActive.bind(li))
+    }
+  })
+
+  nav.querySelector('[data-panel=explore] .context').addEventListener('click', function () {
+    // NOTE logic assumes there are only two panels
+    find(nav, '[data-panel]').forEach(function (panel) {
+      panel.classList.toggle('is-active')
+    })
+  })
+
+  // NOTE prevent text from being selected by double click
+  menuPanel.addEventListener('mousedown', function (e) {
+    if (e.detail > 1) e.preventDefault()
+  })
+
+  function onHashChange () {
+    var navLink
+    var hash = window.location.hash
+    if (hash) {
+      if (hash.indexOf('%')) hash = decodeURIComponent(hash)
+      navLink = menuPanel.querySelector('.nav-link[href="' + hash + '"]')
+      if (!navLink) {
+        var targetNode = document.getElementById(hash.slice(1))
+        if (targetNode) {
+          var current = targetNode
+          var ceiling = document.querySelector('article.doc')
+          while ((current = current.parentNode) && current !== ceiling) {
+            var id = current.id
+            // NOTE: look for section heading
+            if (!id && (id = SECT_CLASS_RX.test(current.className))) id = (current.firstElementChild || {}).id
+            if (id && (navLink = menuPanel.querySelector('.nav-link[href="#' + id + '"]'))) break
+          }
+        }
+      }
+    }
+    var navItem
+    if (navLink) {
+      navItem = navLink.parentNode
+    } else if (originalPageItem) {
+      navLink = (navItem = originalPageItem).querySelector('.nav-link')
+    } else {
+      return
+    }
+    if (navItem === currentPageItem) return
+    find(menuPanel, '.nav-item.is-active').forEach(function (el) {
+      el.classList.remove('is-active', 'is-current-path', 'is-current-page')
+    })
+    navItem.classList.add('is-current-page')
+    currentPageItem = navItem
+    activateCurrentPath(navItem)
+    scrollItemToMidpoint(menuPanel, navLink)
+  }
+
+  if (menuPanel.querySelector('.nav-link[href^="#"]')) {
+    if (window.location.hash) onHashChange()
+    window.addEventListener('hashchange', onHashChange)
+  }
+
+  function activateCurrentPath (navItem) {
+    var ancestorClasses
+    var ancestor = navItem.parentNode

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/02-on-this-page.js
##########
@@ -0,0 +1,114 @@
+;(function () {
+  'use strict'
+
+  var sidebar = document.querySelector('nav.toc.sidebar')
+  if (!sidebar) return
+  if (document.querySelector('body.-toc')) return sidebar.parentNode.removeChild(sidebar)
+  var levels = parseInt(sidebar.dataset.levels || 2, 10)
+  if (levels < 0) return
+
+  var articleSelector = 'article.doc'
+  var article = document.querySelector(articleSelector)
+  var headingsSelector = []
+  for (var level = 0; level <= levels; level++) {
+    var headingSelector = [articleSelector]
+    if (level) {
+      for (var l = 1; l <= level; l++) headingSelector.push((l === 2 ? '.sectionbody>' : '') + '.sect' + l)
+      headingSelector.push('h' + (level + 1) + '[id]')
+    } else {
+      headingSelector.push('h1[id].sect0')
+    }
+    headingsSelector.push(headingSelector.join('>'))
+  }
+  var headings = find(headingsSelector.join(','), article.parentNode)
+  if (!headings.length) return sidebar.parentNode.removeChild(sidebar)
+
+  var lastActiveFragment
+  var links = {}
+  var list = headings.reduce(function (accum, heading) {
+    var link = document.createElement('a')
+    link.textContent = heading.textContent
+    links[(link.href = '#' + heading.id)] = link
+    var listItem = document.createElement('li')
+    listItem.dataset.level = parseInt(heading.nodeName.slice(1), 10) - 1
+    listItem.appendChild(link)
+    accum.appendChild(listItem)
+    return accum
+  }, document.createElement('ul'))
+
+  var menu = sidebar.querySelector('.toc-menu')
+  if (!menu) (menu = document.createElement('div')).className = 'toc-menu'
+
+  var title = document.createElement('h3')
+  title.textContent = sidebar.dataset.title || 'Contents'
+  menu.appendChild(title)
+  menu.appendChild(list)
+
+  var startOfContent = !document.getElementById('toc') && article.querySelector('h1.page ~ :not(.is-before-toc)')
+  if (startOfContent) {
+    var embeddedToc = document.createElement('nav')
+    embeddedToc.className = 'toc embedded'
+    embeddedToc.appendChild(menu.cloneNode(true))
+    startOfContent.parentNode.insertBefore(embeddedToc, startOfContent)
+  }
+
+  window.addEventListener('load', function () {
+    onScroll()
+    window.addEventListener('scroll', onScroll)
+  })
+
+  function onScroll () {
+    var scrolledBy = window.pageYOffset
+    var buffer = getNumericStyleVal(document.documentElement, 'fontSize') * 1.15
+    var ceil = article.offsetTop
+    if (scrolledBy && window.innerHeight + scrolledBy + 2 >= document.documentElement.scrollHeight) {
+      lastActiveFragment = Array.isArray(lastActiveFragment) ? lastActiveFragment : Array(lastActiveFragment || 0)
+      var activeFragments = []
+      var lastIdx = headings.length - 1
+      headings.forEach(function (heading, idx) {
+        var fragment = '#' + heading.id
+        if (idx === lastIdx || heading.getBoundingClientRect().top + getNumericStyleVal(heading, 'paddingTop') > ceil) {
+          activeFragments.push(fragment)
+          if (lastActiveFragment.indexOf(fragment) < 0) links[fragment].classList.add('is-active')

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/03-fragment-jumper.js
##########
@@ -0,0 +1,39 @@
+;(function () {
+  'use strict'
+
+  var article = document.querySelector('article.doc')
+  var toolbar = document.querySelector('.toolbar')
+
+  function decodeFragment (hash) {
+    return hash && (~hash.indexOf('%') ? decodeURIComponent(hash) : hash).slice(1)
+  }
+
+  function computePosition (el, sum) {
+    return article.contains(el) ? computePosition(el.offsetParent, el.offsetTop + sum) : sum
+  }
+
+  function jumpToAnchor (e) {
+    if (e) {
+      if (e.altKey || e.ctrlKey) return
+      window.location.hash = '#' + this.id
+      e.preventDefault()
+    }
+    window.scrollTo(0, computePosition(this, 0) - toolbar.getBoundingClientRect().bottom)
+  }
+
+  window.addEventListener('load', function jumpOnLoad (e) {
+    var fragment, target
+    if ((fragment = decodeFragment(window.location.hash)) && (target = document.getElementById(fragment))) {
+      jumpToAnchor.bind(target)()
+      setTimeout(jumpToAnchor.bind(target), 0)
+    }
+    window.removeEventListener('load', jumpOnLoad)
+  })
+
+  Array.prototype.slice.call(document.querySelectorAll('a[href^="#"]')).forEach(function (el) {
+    var fragment, target
+    if ((fragment = decodeFragment(el.hash)) && (target = document.getElementById(fragment))) {
+      el.addEventListener('click', jumpToAnchor.bind(target))
+    }
+  })
+})()

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/04-page-versions.js
##########
@@ -0,0 +1,17 @@
+;(function () {
+  'use strict'
+
+  var toggle = document.querySelector('.page-versions .version-menu-toggle')
+  if (!toggle) return
+
+  var selector = document.querySelector('.page-versions')
+
+  toggle.addEventListener('click', function (e) {
+    selector.classList.toggle('is-active')
+    e.stopPropagation() // trap event
+  })
+
+  document.documentElement.addEventListener('click', function () {
+    selector.classList.remove('is-active')
+  })
+})()

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/05-mobile-navbar.js
##########
@@ -0,0 +1,20 @@
+;(function () {
+  'use strict'
+
+  var navbarBurger = document.querySelector('.navbar-burger')
+  if (!navbarBurger) return
+  navbarBurger.addEventListener('click', toggleNavbarMenu.bind(navbarBurger))
+
+  function toggleNavbarMenu (e) {
+    e.stopPropagation() // trap event
+    document.documentElement.classList.toggle('is-clipped--navbar')
+    this.classList.toggle('is-active')
+    var menu = document.getElementById(this.dataset.target)
+    if (menu.classList.toggle('is-active')) {
+      menu.style.maxHeight = ''
+      var expectedMaxHeight = window.innerHeight - Math.round(menu.getBoundingClientRect().top)
+      var actualMaxHeight = parseInt(window.getComputedStyle(menu).maxHeight, 10)
+      if (actualMaxHeight !== expectedMaxHeight) menu.style.maxHeight = expectedMaxHeight + 'px'
+    }
+  }
+})()

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/06-copy-to-clipboard.js
##########
@@ -0,0 +1,76 @@
+;(function () {
+  'use strict'
+
+  var CMD_RX = /^\$ (\S[^\\\n]*(\\\n(?!\$ )[^\\\n]*)*)(?=\n|$)/gm
+  var LINE_CONTINUATION_RX = /( ) *\\\n *|\\\n( ?) */g
+  var TRAILING_SPACE_RX = / +$/gm
+  var config = (document.getElementById('site-script') || { dataset: {} }).dataset
+
+  ;[].slice.call(document.querySelectorAll('.doc pre.highlight, .doc .literalblock pre')).forEach(function (pre) {
+    var code, language, lang, copy, toast, toolbox
+    if (pre.classList.contains('highlight')) {
+      code = pre.querySelector('code')
+      if ((language = code.dataset.lang) && language !== 'console') {
+        ;(lang = document.createElement('span')).className = 'source-lang'
+        lang.appendChild(document.createTextNode(language))
+      }
+    } else if (pre.innerText.startsWith('$ ')) {
+      var block = pre.parentNode.parentNode
+      block.classList.remove('literalblock')
+      block.classList.add('listingblock')
+      pre.classList.add('highlightjs', 'highlight')
+      ;(code = document.createElement('code')).className = 'language-console hljs'
+      code.dataset.lang = 'console'
+      code.appendChild(pre.firstChild)
+      pre.appendChild(code)
+    } else {
+      return
+    }
+    ;(toolbox = document.createElement('div')).className = 'source-toolbox'
+    if (lang) toolbox.appendChild(lang)
+    if (window.navigator.clipboard) {
+      ;(copy = document.createElement('button')).className = 'copy-button'
+      copy.setAttribute('title', 'Copy to clipboard')
+      if (config.svgAs === 'svg') {
+        var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+        svg.setAttribute('class', 'copy-icon')
+        var use = document.createElementNS('http://www.w3.org/2000/svg', 'use')
+        use.setAttribute('href', window.uiRootPath + '/img/octicons-16.svg#icon-clippy')
+        svg.appendChild(use)
+        copy.appendChild(svg)
+      } else {
+        var img = document.createElement('img')
+        img.src = window.uiRootPath + '/img/octicons-16.svg#view-clippy'
+        img.alt = 'copy icon'
+        img.className = 'copy-icon'
+        copy.appendChild(img)
+      }
+      ;(toast = document.createElement('span')).className = 'copy-toast'
+      toast.appendChild(document.createTextNode('Copied!'))
+      copy.appendChild(toast)
+      toolbox.appendChild(copy)
+    }
+    pre.appendChild(toolbox)
+    if (copy) copy.addEventListener('click', writeToClipboard.bind(copy, code))
+  })
+
+  function extractCommands (text) {
+    var cmds = []
+    var m
+    while ((m = CMD_RX.exec(text))) cmds.push(m[1].replace(LINE_CONTINUATION_RX, '$1$2'))
+    return cmds.join(' && ')
+  }
+
+  function writeToClipboard (code) {
+    var text = code.innerText.replace(TRAILING_SPACE_RX, '')
+    if (code.dataset.lang === 'console' && text.startsWith('$ ')) text = extractCommands(text)
+    window.navigator.clipboard.writeText(text).then(
+      function () {
+        this.classList.add('clicked')
+        this.offsetHeight // eslint-disable-line no-unused-expressions
+        this.classList.remove('clicked')
+      }.bind(this),
+      function () {}
+    )

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/vendor/highlight.bundle.js
##########
@@ -0,0 +1,40 @@
+;(function () {
+  'use strict'
+
+  var hljs = require('highlight.js/lib/highlight')
+  hljs.registerLanguage('asciidoc', require('highlight.js/lib/languages/asciidoc'))
+  hljs.registerLanguage('bash', require('highlight.js/lib/languages/bash'))
+  hljs.registerLanguage('clojure', require('highlight.js/lib/languages/clojure'))
+  hljs.registerLanguage('cpp', require('highlight.js/lib/languages/cpp'))
+  hljs.registerLanguage('cs', require('highlight.js/lib/languages/cs'))
+  hljs.registerLanguage('css', require('highlight.js/lib/languages/css'))
+  hljs.registerLanguage('diff', require('highlight.js/lib/languages/diff'))
+  hljs.registerLanguage('dockerfile', require('highlight.js/lib/languages/dockerfile'))
+  hljs.registerLanguage('elixir', require('highlight.js/lib/languages/elixir'))
+  hljs.registerLanguage('go', require('highlight.js/lib/languages/go'))
+  hljs.registerLanguage('groovy', require('highlight.js/lib/languages/groovy'))
+  hljs.registerLanguage('haskell', require('highlight.js/lib/languages/haskell'))
+  hljs.registerLanguage('java', require('highlight.js/lib/languages/java'))
+  hljs.registerLanguage('javascript', require('highlight.js/lib/languages/javascript'))
+  hljs.registerLanguage('json', require('highlight.js/lib/languages/json'))
+  hljs.registerLanguage('kotlin', require('highlight.js/lib/languages/kotlin'))
+  hljs.registerLanguage('markdown', require('highlight.js/lib/languages/markdown'))
+  hljs.registerLanguage('nix', require('highlight.js/lib/languages/nix'))
+  hljs.registerLanguage('objectivec', require('highlight.js/lib/languages/objectivec'))
+  hljs.registerLanguage('perl', require('highlight.js/lib/languages/perl'))
+  hljs.registerLanguage('php', require('highlight.js/lib/languages/php'))
+  hljs.registerLanguage('properties', require('highlight.js/lib/languages/properties'))
+  hljs.registerLanguage('puppet', require('highlight.js/lib/languages/puppet'))
+  hljs.registerLanguage('python', require('highlight.js/lib/languages/python'))
+  hljs.registerLanguage('ruby', require('highlight.js/lib/languages/ruby'))
+  hljs.registerLanguage('rust', require('highlight.js/lib/languages/rust'))
+  hljs.registerLanguage('scala', require('highlight.js/lib/languages/scala'))
+  hljs.registerLanguage('shell', require('highlight.js/lib/languages/shell'))
+  hljs.registerLanguage('sql', require('highlight.js/lib/languages/sql'))
+  hljs.registerLanguage('swift', require('highlight.js/lib/languages/swift'))
+  hljs.registerLanguage('xml', require('highlight.js/lib/languages/xml'))
+  hljs.registerLanguage('yaml', require('highlight.js/lib/languages/yaml'))
+  ;[].slice.call(document.querySelectorAll('pre code.hljs')).forEach(function (node) {
+    hljs.highlightBlock(node)
+  })
+})()

Review comment:
       *W033:*  Missing semicolon.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)

##########
File path: solr/solr-ref-guide/ui/src/js/03-fragment-jumper.js
##########
@@ -0,0 +1,39 @@
+;(function () {
+  'use strict'
+
+  var article = document.querySelector('article.doc')
+  var toolbar = document.querySelector('.toolbar')
+
+  function decodeFragment (hash) {
+    return hash && (~hash.indexOf('%') ? decodeURIComponent(hash) : hash).slice(1)
+  }
+
+  function computePosition (el, sum) {
+    return article.contains(el) ? computePosition(el.offsetParent, el.offsetTop + sum) : sum
+  }
+
+  function jumpToAnchor (e) {
+    if (e) {
+      if (e.altKey || e.ctrlKey) return
+      window.location.hash = '#' + this.id
+      e.preventDefault()
+    }
+    window.scrollTo(0, computePosition(this, 0) - toolbar.getBoundingClientRect().bottom)

Review comment:
       *W040:*  If a strict mode function is executed using function invocation, its 'this' value will be undefined.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org