diff --git a/preview-src/index.adoc b/preview-src/index.adoc index a93fc127..dcee087e 100644 --- a/preview-src/index.adoc +++ b/preview-src/index.adoc @@ -39,6 +39,55 @@ As the selected interval increases, the amount of statistical data displayed wil Click the image:git-branch.svg[,16,role=icon] icon at the bottom of the editor to select a branch. Then click the image:arrow-small-down.svg[,16,role=icon]image:arrow-small-up.svg[,16,role=icon] icons to open the pull/push dialog. +== Try It Now + +This section demonstrates the interactive, try it now feature of the docs. + +[source.try-it,ruby] +---- +require 'couchbase' + +options = Couchbase::Cluster::ClusterOptions.new +options.authenticate('username', 'password') +cluster = Couchbase::Cluster.connect('couchbase://127.0.0.1', options) + +bucket = cluster.bucket('travel-sample') +collection = bucket.default_collection + +begin + get_result = collection.get('airline_10') + puts get_result.content +rescue Couchbase::Error::DocumentNotFound + puts 'Document not found!' +end +---- + +[source.try-it,java] +---- +import com.couchbase.client.core.error.DocumentNotFoundException; +import com.couchbase.client.java.*; +import com.couchbase.client.java.kv.*; + +public class StartUsing { + public static void main(String[] args) { + var cluster = Cluster.connect( + "couchbase://127.0.0.1", "username", "password" + ); + + var bucket = cluster.bucket("travel-sample"); + var collection = bucket.defaultCollection(); + + try { + var result = collection.get("airline_10"); + System.out.println(result.toString()); + + } catch (DocumentNotFoundException ex) { + System.out.println("Document not found!"); + } + } +} +---- + == Individual Bucket Monitoring Bucket monitoring within the Couchbase Web Console has been updated to show additional detailed information. diff --git a/src/css/clipboard.css b/src/css/clipboard.css index e938c541..56a596e8 100644 --- a/src/css/clipboard.css +++ b/src/css/clipboard.css @@ -1,50 +1,14 @@ -.view-source-button { +.view-source-button, +.copy-code-button { color: var(--color-brand-gray4); display: inline-block; - margin-left: 0.5rem; -} - -.view-source-button:hover::after { - content: attr(data-title); - color: var(--color-brand-gray4); - font-size: var(--font-base); - font-weight: var(--weight-light); - line-height: 1; - text-transform: capitalize; - position: absolute; - bottom: -53px; - right: -30%; - left: auto; - margin: 0; - padding: 5px; - text-align: center; - box-shadow: 0 3px 6px rgba(0, 0, 0, 0.06); - background: var(--color-brand-white); - border: 1px solid var(--color-brand-gray7); - box-sizing: border-box; - border-radius: 3px; - min-width: 90px; - font-family: "Source Sans Pro", sans-serif; -} - -.view-source-button:hover::before { - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 10px solid var(--color-brand-white); - position: absolute; - content: ""; - box-shadow: inset 0 0 1px #bec0c1; - bottom: -27px; - right: auto; - left: auto; + position: relative; + cursor: pointer; } -.copy-code-button { - color: var(--color-brand-gray4); - cursor: pointer; - display: inline-block; - margin-left: 0.5rem; - margin-right: 0.5rem; +.view-source-button:hover, +.copy-code-button:hover { + text-decoration: none; } a.view-source-button:focus, @@ -54,39 +18,37 @@ a.copy-code-button:hover { color: var(--color-brand-gray4); } +.view-source-button:hover::after, .copy-code-button:hover::after { + content: ""; + border: 7px solid transparent; + border-bottom: 10px solid var(--color-brand-white); + position: absolute; + box-shadow: inset 0 0 1px #bec0c1; + top: 7px; + left: 50%; + margin-left: -7px; + pointer-events: none; +} + +.view-source-button:hover::before, +.copy-code-button:hover::before { content: attr(data-title); - color: var("--color-brand-gray4"); + color: var(--color-brand-gray4); font-size: var(--font-base); font-weight: var(--weight-light); - line-height: 1; - text-transform: capitalize; position: absolute; - bottom: -53px; - right: -30%; - left: auto; - margin: 0; - padding: 5px; + top: 14px; + left: 50%; + transform: translateY(100%) translateX(-50%); + padding: 3px 1em; text-align: center; box-shadow: 0 3px 6px rgba(0, 0, 0, 0.06); background: var(--color-brand-white); border: 1px solid var(--color-brand-gray7); - box-sizing: border-box; border-radius: 3px; - min-width: 80px; font-family: "Source Sans Pro", sans-serif; -} - -.copy-code-button:hover::before { - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 10px solid var(--color-brand-white); - position: absolute; - content: ""; - box-shadow: inset 0 0 1px #bec0c1; - bottom: -27px; - right: auto; - left: auto; + pointer-events: none; } .doc .listingblock code[data-lang] + .source-type-box { @@ -101,7 +63,7 @@ a.copy-code-button:hover { .doc .listingblock code[data-lang] + .source-type-box .data-source { content: attr(data-lang); - color: var("--color-brand-gray1"); + color: var(--color-brand-gray1); font-size: 0.75rem; font-weight: var(--weight-normal); letter-spacing: 1px; @@ -120,6 +82,10 @@ a.copy-code-button:hover { display: flex; } +.doc .listingblock code[contenteditable] { + outline: none; +} + .doc .listingblock pre .fade-shadow { display: none; background: @@ -160,3 +126,56 @@ code::-webkit-scrollbar { code::-webkit-scrollbar-thumb { background-color: var(--color-border); } + +/* New style code block */ +.source-type-box { + padding-left: 12px; + border: 1px solid #e5e5e5; + border-bottom: none; + border-radius: 3px 3px 0 0; + display: flex; + justify-content: space-between; + font-size: 14px; + line-height: 20px; + color: #73768a; + font-family: 'Source Code Pro', monospace; + z-index: 1; + position: relative; +} + +.source-type-box .right-block { + display: flex; +} + +.source-type-box .right-block > * { + border-right: 1px solid #e5e5e5; + padding: 4px 10px; + display: flex; + align-items: center; +} + +.source-type-box .right-block > *:last-child { + border: none; +} + +.doc .listingblock .source-type-box .data-source { + text-transform: uppercase; + letter-spacing: 0.025em; + font-weight: var(--weight-medium); +} + +.copy-code-button .svg-inline--fa, +.run-code .svg-inline--fa { + margin-right: 5px; +} + +.run-code { + background: #0074e0; + color: #fff; + cursor: pointer; +} + +.run-code:hover { + text-decoration: none; + color: #fff; +} diff --git a/src/css/doc.css b/src/css/doc.css index 3f3f64a0..845ef306 100644 --- a/src/css/doc.css +++ b/src/css/doc.css @@ -593,7 +593,7 @@ ul ul ul { overflow-x: auto; background: #0074e00e; border: 1px solid var(--color-brand-gray8); - border-radius: 3px; + border-radius: 0 0 3px 3px; position: relative; } diff --git a/src/css/site.css b/src/css/site.css index 76cc13b4..158fdc4e 100644 --- a/src/css/site.css +++ b/src/css/site.css @@ -27,3 +27,4 @@ @import "table.css"; @import "landing-page.css"; @import "contributor.css"; +@import "terminal.css"; diff --git a/src/css/terminal.css b/src/css/terminal.css new file mode 100644 index 00000000..86189062 --- /dev/null +++ b/src/css/terminal.css @@ -0,0 +1,84 @@ +.action-panel { + display: none; + position: absolute; + top: 0; + bottom: 0; + left: 50%; + width: 50%; + background-color: #f1f7fe; + flex-direction: column; +} + +.action-panel .run-code-output { + border: 0; + flex-grow: 1; +} + +.terminal-launched, +.terminal-launched body { + overflow: hidden; +} + +.terminal-launched .action-panel { + display: flex; +} + +.terminal-launched .left-sidebar, +.terminal-launched .toc.sidebar, +.terminal-launched footer { + display: none; +} + +.action-panel .controls { + display: flex; + background: #fff; + border-bottom: 1px solid #e5e5e5; +} + +.action-panel .control-button, +.action-panel .control-label { + padding: 4px 10px; + font-size: 14px; + line-height: 20px; + color: #73768a; +} + +.action-panel .control-button { + border: 0; + background: transparent; +} + +.action-panel .control-label { + flex-grow: 1; +} + +.action-panel .controls > * + * { + border-left: 1px solid #e5e5e5; +} + +.action-panel .close { + display: flex; + align-items: center; +} + +.action-panel .close svg { + margin-right: 10px; +} + +@media all and (min-width: 768px) { + .terminal-launched .body.container { + position: relative; + } + + .terminal-launched main.article { + width: 50%; + position: absolute; + overflow-x: hidden; + overflow-y: scroll; + top: 0; + bottom: 0; + left: 0; + padding-right: var(--width-main-gutter); + padding-left: var(--width-main-gutter); + } +} diff --git a/src/js/01-nav.js b/src/js/01-nav.js index 12c818fa..96ff5980 100644 --- a/src/js/01-nav.js +++ b/src/js/01-nav.js @@ -102,7 +102,7 @@ if (startCollapsed) componentVersionNavEl.classList.add('hide') var items = componentVersion.sets if (items.length === 1 && !items[0].content) items = items[0].items - if (items.length && items[0].content.endsWith(' Home')) { + if (items.length && items[0].content && items[0].content.endsWith(' Home')) { items.splice.apply(items, [0, 1].concat(items[0].items || [])) } if (buildNavTree(items, componentVersionNavEl, page, [])) hasNavTrees = true diff --git a/src/js/07-copy-to-clipboard.js b/src/js/07-copy-to-clipboard.js index 50eda65b..dd3579df 100644 --- a/src/js/07-copy-to-clipboard.js +++ b/src/js/07-copy-to-clipboard.js @@ -1,11 +1,14 @@ ;(function () { 'use strict' + var runCodeLangs = { cpp: 'cc', csharp: 'dotnet', js: 'nodejs', python: 'py', ruby: 'rb' } + var main = document.querySelector('main.article') document.querySelectorAll('pre > code').forEach(function (codeBlock) { + var pre = codeBlock.parentNode var viewSourceLink var sourceUrl = codeBlock.dataset.sourceUrl if (sourceUrl) { viewSourceLink = document.createElement('a') - viewSourceLink.href = codeBlock.dataset.sourceUrl + viewSourceLink.href = sourceUrl viewSourceLink.className = 'view-source-button' viewSourceLink.target = '_blank' viewSourceLink.dataset.title = 'View On GitHub' @@ -13,10 +16,19 @@ } var sourceTypeBox = document.createElement('div') sourceTypeBox.className = 'source-type-box' + + var headingBox = document.createElement('div') + headingBox.className = 'col-2 left-block' + + var sourceTypeBoxCol2 = document.createElement('div') + sourceTypeBoxCol2.className = 'col-2 right-block' + var copyButton = document.createElement('a') copyButton.className = 'copy-code-button' copyButton.dataset.title = 'Copy' copyButton.appendChild(document.createElement('i')).className = 'far fa-copy' + var copyText = document.createTextNode('Copy') + copyButton.appendChild(copyText) var dataSource = document.createElement('span') dataSource.className = 'data-source' @@ -26,8 +38,6 @@ fadeShadow.className = 'fade-shadow' copyButton.addEventListener('click', function (e) { - // NOTE: ignore event on pseudo-element - if (e.currentTarget === e.target) return var bashText = codeBlock.innerText // remove '$' from copy to code functionality in code block console // var spliceData = bashText.split('$').join('') @@ -65,11 +75,74 @@ ) } }) - var pre = codeBlock.parentNode - pre.appendChild(sourceTypeBox) - sourceTypeBox.appendChild(dataSource) - if (viewSourceLink) sourceTypeBox.appendChild(viewSourceLink) - sourceTypeBox.appendChild(copyButton) + + var runCodeButton + if (codeBlock.matches('.listingblock.try-it code') || + (codeBlock.matches('#full-example + .sectionbody .listingblock code'))) { + codeBlock.contentEditable = true + codeBlock.spellcheck = false + runCodeButton = document.createElement('a') + runCodeButton.className = 'run-code' + runCodeButton.dataset.title = 'Run Code' + runCodeButton.appendChild(document.createElement('i')).className = 'fas fa-terminal' + var runCodeButtonText = document.createTextNode('Run Code') + runCodeButton.appendChild(runCodeButtonText) + var runCodePanel = createRunCodePanel(main.parentNode) + runCodeButton.addEventListener('click', function (e) { + var currentY = this.getBoundingClientRect().top + document.documentElement.classList.add('terminal-launched') + var newY = this.getBoundingClientRect().top + main.scrollBy(0, newY - currentY) + rebuildRunCodeFrame(runCodePanel) + var runCodeForm = runCodePanel.querySelector('form') + runCodeForm.lang.value = runCodeLangs[codeBlock.dataset.lang] || codeBlock.dataset.lang + var code = codeBlock.innerText + if (runCodeForm.lang.value === 'java') code = code.replace(/^(?:public )?class \S+/m, 'class Program') + runCodeForm.code.value = code + runCodeForm.submit() + }) + } + + pre.prepend(sourceTypeBox) + sourceTypeBox.appendChild(headingBox) + sourceTypeBox.appendChild(sourceTypeBoxCol2) + sourceTypeBoxCol2.appendChild(dataSource) + if (viewSourceLink) sourceTypeBoxCol2.appendChild(viewSourceLink) + sourceTypeBoxCol2.appendChild(copyButton) + if (runCodeButton) sourceTypeBoxCol2.appendChild(runCodeButton) pre.appendChild(fadeShadow) }) + + function createRunCodePanel (scope) { + var runCodePanel = document.getElementById('run-code-panel') + if (runCodePanel.tagName !== 'TEMPLATE') return runCodePanel + var template = runCodePanel + runCodePanel = scope.appendChild(template.content.firstElementChild.cloneNode(true)) + runCodePanel.querySelector('.rerun').addEventListener('click', function () { + rebuildRunCodeFrame(runCodePanel) + }) + runCodePanel.querySelector('.close').addEventListener('click', function () { + var main = scope.querySelector('main') + var viewportTop = main.getBoundingClientRect().top + var ref = Array.prototype.slice.call(main.querySelectorAll('*')).find(function (it) { + return it.getBoundingClientRect().top >= viewportTop + }) + var currentY = ref.getBoundingClientRect().top + document.documentElement.classList.remove('terminal-launched') + var newY = ref.getBoundingClientRect().top + document.documentElement.style.scrollBehavior = 'auto' + document.documentElement.scrollBy(0, newY - currentY) + document.documentElement.style.scrollBehavior = '' + }) + template.parentNode.removeChild(template) + runCodePanel.id = 'run-code-panel' + return runCodePanel + } + + function rebuildRunCodeFrame (scope) { + var runCodeFrameTemplate = scope.querySelector('iframe') + var runCodeFrame = runCodeFrameTemplate.cloneNode() + scope.replaceChild(runCodeFrame, runCodeFrameTemplate) + runCodeFrame.contentWindow.document.write('
Running code...
') + } })() diff --git a/src/js/vendor/fontawesome-icon-defs.js b/src/js/vendor/fontawesome-icon-defs.js index fcb1bf7a..54dac378 100644 --- a/src/js/vendor/fontawesome-icon-defs.js +++ b/src/js/vendor/fontawesome-icon-defs.js @@ -1,2 +1,2 @@ -/*! iconNames: ['far fa-copy', 'fas fa-link', 'fab fa-github'] */ +/*! iconNames: ['far fa-copy', 'fas fa-link', 'fab fa-github', 'fas fa-terminal'] */ window.FontAwesomeIconDefs = [] diff --git a/src/partials/footer-scripts.hbs b/src/partials/footer-scripts.hbs index 83fa962e..34c7b143 100644 --- a/src/partials/footer-scripts.hbs +++ b/src/partials/footer-scripts.hbs @@ -7,6 +7,9 @@ {{/with}} {{/if}} + {{#with page.attributes.content-scripts}} {{{this}}} diff --git a/src/partials/terminal.hbs b/src/partials/terminal.hbs new file mode 100644 index 00000000..823f8f36 --- /dev/null +++ b/src/partials/terminal.hbs @@ -0,0 +1,13 @@ +
+
+ + + +
+ + Output + +
+
+ +