diff --git a/README.adoc b/README.adoc index 92aede8..68d2764 100644 --- a/README.adoc +++ b/README.adoc @@ -1,159 +1,25 @@ -= {company} {product} Docs += {company} {product} docs // Variables: :company: DataStax :product: Pulsar Connector -:repo-name: pulsar-sink-docs -:github-org: datastax -// Settings: +// Document settings: :toc: macro +:toclevels: 2 +:idprefix: +:idseparator: - :!example-caption: +:!figure-caption: +:!table-caption: :experimental: :hide-uri-scheme: ifdef::env-github[] -:icons: font -:toclevels: 1 -:toc-title: Contents :tip-caption: :bulb: -:note-caption: :information_source: +:note-caption: :paperclip: :important-caption: :heavy_exclamation_mark: :caution-caption: :fire: :warning-caption: :warning: -:badges: endif::[] -// Project URLs: -:url-github-org: https://github.com/{github-org} -:url-project-repo: {url-github-org}/{repo-name} -:url-ui-repo: https://github.com/riptano/docs-ui -:url-playbook-repo: https://github.com/riptano/datastax-docs-site -:url-contribute: -:url-datastax: https://datastax.com -:url-datastax-docs: https://docs.datastax.com -:url-docs-preview: http://docs-preview.datastax.com -// External URLs: -:asciidoc-language: https://docs.asciidoctor.org/asciidoc/latest/ -This repository contains the source files for the {company} {product} documentation. +This repository contains the https://docs.asciidoctor.org/asciidoc/latest/[AsciiDoc] source files for the {company} {product} documentation. -toc::[] - -== Get started - -The documentation is written in {asciidoc-language}[AsciiDoc]-formatted source files located in the `modules` directory. - -=== Make a simple update - -For simple updates like fixing typos or modifying existing prose, it's easiest to edit the source files directly on GitHub. - -NOTE: You'll need Write privileges on the repository to edit files directly on GitHub. - -. Find the file you want to edit in the `modules` directory. - -. Click the *Edit* icon in the upper-right corner of the file view. - -. Make your changes in the editor. - -. Click *Commit changes...* - -. Enter a description for your commit and click *Propose changes*. - -. On the *Open a pull request* screen, enter a title and description for your change, assign reviewers, then click *Create pull request*. - -. Once the pull request is open, an automatic draft preview build is triggered. -Once complete, the build system posts a comment on the pull request with a link to the draft site for you to preview your changes. - -=== Edit docs locally - -If you need to make substantial updates to the documentation, you'll want to clone the repository so you can work with the source files locally. - -. Clone this repository -+ -[source,bash,subs="attributes"] ----- -git clone {url-project-repo}.git ----- - -. https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic[Create a _classic_ personal access token] for your GitHub account. -When configuring the token, set the *Expiration* to at least 90 days and select everything under the *Repo* https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes[scope]. -+ -[IMPORTANT] -==== -Copy your personal access token to a temporary location -- you'll need it later. -==== - -. https://docs.github.com/en/enterprise-cloud@latest/authentication/authenticating-with-saml-single-sign-on/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on[Authorize your personal access token] so that it can access repositories in the Riptano and DataStax organizations in GitHub. - -. https://docs.antora.org/antora/latest/playbook/private-repository-auth/#populate-credentials-directly[Populate the credential store] with your personal access token. -For most people this means doing the following: -+ -.. Create the file `$HOME/.git-credentials` and open it in your editor. -.. Add the following line: -+ -[source,subs="verbatim,quotes"] ----- -https://**TOKEN**:@github.com ----- -+ -Replace *`TOKEN`* with the personal access token you copied from GitHub. -.. Save and close the file. - -. If you don't already have Node.js installed, do the following: - -.. Install https://github.com/nvm-sh/nvm[nvm]. -+ -If you're on macOS, you can install nvm using https://brew.sh/[Homebrew]: -+ -[source,bash] ----- -brew install nvm ----- - -.. Use nvm to install Node.js. -+ -[source,bash] ----- -nvm install --lts ----- -+ -[source,bash] ----- -nvm use --lts ----- -+ -[source,bash] ----- -nvm alias default node ----- - -. Install the project dependencies. -+ -[source,bash,subs="attributes"] ----- -cd {repo-name} ----- -+ -[source,bash] ----- -npm install ----- - -. Build the site. -+ -[source,bash] ----- -npm run build:local ----- -+ -If the build was successful, you'll see the following output in your terminal: -+ -[source,console,subs="attributes"] ----- -Site generation complete! -Open file:///Users/USERNAME/repos/{repo-name}/build/site/index.html in a browser to view your site. ----- -+ -To view the site, paste the entire `\file:///` path into your browser's address bar and press kbd:[Return]. - -[#publish-docs] -== Publish docs - -To learn how to publish documentation to {url-datastax-docs}, see the {url-playbook-repo}#deploy-production[datastax-docs-site README]. +To learn how to update the documentation, see the https://datastax.jira.com/wiki/spaces/DOCS/overview[Docs team Confluence site]. diff --git a/lib/assets-processor.js b/lib/assets-processor.js deleted file mode 100644 index 7d1e5e7..0000000 --- a/lib/assets-processor.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -module.exports.register = (context) => { - const logger = context.getLogger("assets-processor-extension"); - - context.once("uiLoaded", ({ uiCatalog }) => { - const manifestContents = uiCatalog - .findByType("asset") - .find((file) => file.stem === "assets-manifest") - .contents?.toString(); - if (!manifestContents) { - logger.error("Could not find assets-manifest.json in the UI bundle."); - return; - } - const manifest = JSON.parse(manifestContents); - // Add manifest to node global context so it can be accessed by the handlebars helper during createPageComposer - global.assetsManifest = manifest; - }); - - context.once("pagesComposed", () => { - // Clean up the global context - delete global.assetsManifest; - }); -}; diff --git a/lib/remote-include-processor.js b/lib/remote-include-processor.js deleted file mode 100644 index 731a0a0..0000000 --- a/lib/remote-include-processor.js +++ /dev/null @@ -1,199 +0,0 @@ -const CIRCUMFIX_COMMENT_SUFFIX_RX = / (?:\*[/)]|--%?>)$/ -const NEWLINE_RX = /\r\n?|\n/ -const TAG_DELIMITER_RX = /[,;]/ -const TAG_DIRECTIVE_RX = /\b(?:tag|(end))::(\S+)\[\]$/ -const LINES_DOTDOT_RX = /\.\./ - - -function getTags (attrs) { - if ( 'tag' in attrs ) { - const tag = attrs['tag'] - if (tag && tag !== '!') { - return tag.charAt() === '!' ? new Map().set(tag.substr(1), false) : new Map().set(tag, true) - } - } else if ( 'tags' in attrs ) { - const tags = attrs['tags'] - if (tags) { - let result = new Map() - let any = false - tags.split(TAG_DELIMITER_RX).forEach((tag) => { - if (tag && tag !== '!') { - any = true - tag.charAt() === '!' ? result.set(tag.substr(1), false) : result.set(tag, true) - } - }) - if (any) return result - } - } -} - - -function applyTagFiltering (contents, tags) { - let selecting, selectingDefault, wildcard - if (tags.has('**')) { - if (tags.has('*')) { - selectingDefault = selecting = tags.get('**') - wildcard = tags.get('*') - tags.delete('*') - } else { - selectingDefault = selecting = wildcard = tags.get('**') - } - tags.delete('**') - } else { - selectingDefault = selecting = !Array.from(tags.values()).includes(true) - if (tags.has('*')) { - wildcard = tags.get('*') - tags.delete('*') - } - } - - const lines = [] - const tagStack = [] - const usedTags = [] - let activeTag - let lineNum = 0 - let startLineNum - contents.split(NEWLINE_RX).forEach((line) => { - lineNum++ - let m - let l = line - if ( - (l.endsWith('[]') || - (~l.indexOf('[] ') && - (m = l.match(CIRCUMFIX_COMMENT_SUFFIX_RX)) && - (l = l.substr(0, m.index)).endsWith('[]'))) && - (m = l.match(TAG_DIRECTIVE_RX)) - ) { - const thisTag = m[2] - if (m[1]) { - if (thisTag === activeTag) { - tagStack.shift() - ;[activeTag, selecting] = tagStack.length ? tagStack[0] : [undefined, selectingDefault] - } else if (tags.has(thisTag)) { - const idx = tagStack.findIndex(([name]) => name === thisTag) - if (~idx) { - tagStack.splice(idx, 1) - //console.warn(`line ${lineNum}: mismatched end tag in include: expected ${activeTag}, found ${thisTag}`) - } - //} else { - // //console.warn(`line ${lineNum}: unexpected end tag in include: ${thisTag}`) - //} - } - } else if (tags.has(thisTag)) { - usedTags.push(thisTag) - tagStack.unshift([(activeTag = thisTag), (selecting = tags.get(thisTag))]) - } else if (wildcard !== undefined) { - selecting = activeTag && !selecting ? false : wildcard - tagStack.unshift([(activeTag = thisTag), selecting]) - } - } else if (selecting) { - if (!startLineNum) startLineNum = lineNum - lines.push(line) - } - }) - // Q: use _.difference(Object.keys(tags), usedTags)? - //const missingTags = Object.keys(tags).filter((e) => !usedTags.includes(e)) - //if (missingTags.length) { - // console.warn(`tag${missingTags.length > 1 ? 's' : ''} '${missingTags.join(',')}' not found in include`) - //} - return [lines, startLineNum || 1] -} - -function getLines (attrs) { - if ( 'lines' in attrs ) { - const lines = attrs['lines'] - if (lines) { - // console.warn(`have lines` + lines) - let result = [] // new Map() - let any = false - lines.split(TAG_DELIMITER_RX).forEach((line) => { - if (line && line !== '!') { - let tryMultipleLines = line.split(LINES_DOTDOT_RX) - if ( tryMultipleLines.length === 1 ) { - any = true - result.push([tryMultipleLines[0], tryMultipleLines[0]]) - } - else if ( tryMultipleLines.length === 2 ) { - any = true - result.push([tryMultipleLines[0], tryMultipleLines[1]]) - } - } - }) - if (any) return result - } - } -} - -function filterChars(content){ - let myRegexp = new RegExp(/[^${\}]+(?=})/g); - let matches = myRegexp.exec(content); - - if(matches == null) - return content; - - let ret = content; - // matches.forEach(x => { - // let a = new RegExp("\\${"+x+"}",'gm'); - // ret = ret.replace(a,'asd'); - // }) - - return ret; -} - -function applyLineFiltering (contents, linesToInclude) { - const lines = [] - let lineNum = 0 - let startLineNum - let registerCurrentLine = false - - const nLinesPair = linesToInclude.length - let currentLinePair = 0 - let startLine = linesToInclude[currentLinePair][0] - let endLine = linesToInclude[currentLinePair][1] - // console.warn(`applyLineFiltering ` + startLine + ' and ' + endLine ) - - contents.split(NEWLINE_RX).forEach((line) => { - lineNum++ - - if ( !registerCurrentLine ) { - if ( lineNum == startLine ) - registerCurrentLine = true - } - - if ( registerCurrentLine ) - { - if (!startLineNum) startLineNum = lineNum - lines.push(line) - - if ( lineNum == endLine ) { - registerCurrentLine = false - currentLinePair++ - if ( currentLinePair >= nLinesPair ) - return [lines, startLineNum] - else { - startLine = linesToInclude[currentLinePair][0] - endLine = linesToInclude[currentLinePair][1] - } - } - } - }) - return [lines, startLineNum || 1] -} - -module.exports = function () { - this.includeProcessor(function () { - this.$option('position', '>>') - this.handles((target) => target.startsWith('https://')) - this.process((doc, reader, target, attrs) => { - const contents = require('child_process').execFileSync('curl', ['--silent', '-L', target], { encoding: 'utf8' }) - let includeContents = filterChars(contents) - let startLineNum = 1 - const tags = getTags(attrs) - const lines = getLines(attrs) - if (tags) [includeContents, startLineNum] = applyTagFiltering(includeContents, tags) - else if (lines) [includeContents, startLineNum] = applyLineFiltering(includeContents, lines) - reader.pushInclude(includeContents, target, target, startLineNum, attrs) - // reader.pushInclude(contents, target, target, 1, attrs) - }) - }) -} diff --git a/lib/svg-macro.js b/lib/svg-macro.js deleted file mode 100644 index e7f5928..0000000 --- a/lib/svg-macro.js +++ /dev/null @@ -1,110 +0,0 @@ -const logger = require("@antora/logger")("asciidoctor:svg-macro"); - -/** - * @example Inline Embedded SVG - * svg:ROOT:ui/icons/vector.svg[] - */ -function inlineSvgMacro({ contentCatalog, file }) { - return function () { - this.process((parent, target, attrs) => { - svgContent = getSvgContent(target, file, contentCatalog); - if (!svgContent) return; - return this.createInlinePass( - parent, - svgContent.replace(" { - svgContent = getSvgContent(target, file, contentCatalog); - if (!svgContent) return; - const svgHtmlAttrs = htmlAttrs({ ...attrs, role: undefined }); - const containerHtmlAttrs = attrs.role - ? `class="imageblock ${attrs.role}"` - : 'class="imageblock"'; - const html = - `
` + - svgContent.replace("
"; - return this.createBlock(parent, "pass", html); - }); - }; -} - -/** - * This macro relies on the material-icons font being loaded in UI bundle. - * - * @example Material Icon - * icon:material-icons:menu_open[] - * - * @example Embedded SVG - * icon:ROOT:ui/icons/vector.svg[] - */ -function inlineIconMacro({ contentCatalog, file }) { - return function () { - this.process((parent, target, attrs) => { - if (target.startsWith("material-icons")) { - iconTarget = target - .replace("material-icons:", "") - .trim() - .replace("-", "_"); - return this.createInlinePass( - parent, - `${iconTarget}` - ); - } else { - svgContent = getSvgContent(target, file, contentCatalog); - if (!svgContent) return; - return this.createInlinePass( - parent, - svgContent.replace(" { - context.once("sitePublished", ({ playbook }) => { - const logger = context.getLogger('tailwind-processor-extension') - const outputDir = playbook?.output?.dir || "build/site"; - logger.info("Building Tailwind"); - var configPath = execSync(`find ${outputDir} -name tailwind.config.js`) - .toString() - .trim(); - var cssPath = execSync(`find ${outputDir} -name site*.css`) - .toString() - .trim(); - logger.info( - `npm run tailwindcss --tailwind-config-path=${configPath} --css-path=${cssPath}` - ); - execSync( - `npm run tailwindcss --tailwind-config-path=${configPath} --css-path=${cssPath}`, - { stdio: "inherit" } - ); - logger.info("Tailwind Build Successful"); - }); -}; diff --git a/lib/unlisted-pages-extension.js b/lib/unlisted-pages-extension.js deleted file mode 100644 index d588690..0000000 --- a/lib/unlisted-pages-extension.js +++ /dev/null @@ -1,41 +0,0 @@ -module.exports.register = function ({ config }) { - const { addToNavigation, unlistedPagesHeading = 'Unlisted Pages' } = config - const logger = this.getLogger('unlisted-pages-extension') - this - .on('navigationBuilt', ({ contentCatalog }) => { - contentCatalog.getComponents().forEach(({ versions }) => { - versions.forEach(({ name: component, version, navigation: nav, url: defaultUrl }) => { - const navEntriesByUrl = getNavEntriesByUrl(nav) - const unlistedPages = contentCatalog - .findBy({ component, version, family: 'page' }) - .filter((page) => page.out) - .reduce((collector, page) => { - // Check if the 'unlisted-page' attribute is set to true - if (page.asciidoc.attributes['unlisted-page'] === 'true') { - return collector; // Skip this page - } - if ((page.pub.url in navEntriesByUrl) || page.pub.url === defaultUrl) return collector - logger.warn({ file: page.src, source: page.src.origin }, 'detected unlisted page') - return collector.concat(page) - }, []) - if (unlistedPages.length && addToNavigation) { - nav.push({ - content: unlistedPagesHeading, - items: unlistedPages.map((page) => { - return { content: page.asciidoc.navtitle, url: page.pub.url, urlType: 'internal' } - }), - root: true, - }) - } - }) - }) - }) - } - - function getNavEntriesByUrl (items = [], accum = {}) { - items.forEach((item) => { - if (item.urlType === 'internal') accum[item.url.split('#')[0]] = item - getNavEntriesByUrl(item.items, accum) - }) - return accum - } diff --git a/local-preview-playbook.yml b/local-preview-playbook.yml deleted file mode 100644 index e2f743f..0000000 --- a/local-preview-playbook.yml +++ /dev/null @@ -1,91 +0,0 @@ -runtime: - log: - failure_level: warn -git: - # ensure_git_suffix: false # Enable if necessary -- some git services don’t recognize the URL if it contains the .git extension. - fetch_concurrency: 10 - -site: - title: DataStax Docs - start_page: pulsar-connector::index.adoc - robots: disallow - -content: - branches: main # Sources default to this branch if none are specified. - sources: - - url: . - start_path: docs-src/pulsar-sink-core - branches: HEAD - -antora: - extensions: - - '@antora/atlas-extension' - - '@antora/collector-extension' - - lib/assets-processor.js - - lib/tailwind-processor.js - - id: unlisted-pages - enabled: true - require: lib/unlisted-pages-extension.js - add_to_navigation: false - unlisted_pages_heading: Orphans - -asciidoc: - extensions: - - '@asciidoctor/tabs' - - lib/remote-include-processor.js - - lib/svg-macro.js - - asciidoctor-kroki - - asciidoctor-external-callout - attributes: - # BUILT-IN ATTRIBUTES - # allow-uri-read: '' # Quality-of-life benefit for IntelliJ users. CAUTION: Opens the door to malicious code insertion - must remain disabled in prod build environment. - # hide-uri-scheme: '' # Consider enabling this attribute to make raw http hyperlinks look cleaner. - experimental: '' - idprefix: '' - idseparator: '-' - # kroki-fetch-diagram: true - # kroki-server-url: - max-include-depth: 10 - page-toclevels: 2@ - sectlinks: '' - tabs-sync-option: '' - example-caption: false - figure-caption: false - table-caption: false - xrefstyle: short - # CUSTOM ATTRIBUTES - company: 'DataStax' - astra_db: 'Astra DB' - astra_stream: 'Astra Streaming' - astra_ui: 'Astra Portal' - astra_cli: 'Astra CLI' - astra-streaming-examples-repo: 'https://raw.githubusercontent.com/datastax/astra-streaming-examples/master' - luna-streaming-examples-repo: 'https://raw.githubusercontent.com/datastaxdevs/luna-streaming-examples/main' - support_url: 'https://support.datastax.com' - glossary-url: 'https://docs.datastax.com/en/glossary/docs/index.html#' - emoji-tada: "🎉" - emoji-rocket: "🚀" - emoji-smile: "😀" - dse: 'DataStax Enterprise (DSE)' - cassandra: 'Apache Cassandra(R)' - classic: 'classic' - classic_cap: 'Classic' - serverless: 'serverless' - serverless_cap: 'Serverless' - # Antora Atlas - primary-site-url: https://docs.datastax.com/en - primary-site-manifest-url: https://docs.datastax.com/en/site-manifest.json - -urls: - latest_version_segment_strategy: redirect:from - latest_version_segment: 'latest' - -ui: - bundle: - url: https://github.com/riptano/docs-ui/releases/latest/download/ui-bundle.zip - # url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable - snapshot: true - # supplemental_files: supplemental-ui - -output: - dir: 'build/site' \ No newline at end of file diff --git a/package.json b/package.json index a99afb8..d2a03d9 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,6 @@ { "private": true, - "name": "pulsar-sink-docs", - "description": "The content source for DataStax Apache Pulsar Connector documentation.", - "author": "DataStax Inc.", - "homepage": "https://docs.datastax.com", - "repository": { - "type": "git", - "url": "https://github.com/datastax/pulsar-sink-docs.git" - }, "scripts": { - "tailwindcss": "tailwindcss build -c ${npm_config_tailwind_config_path} -i ${npm_config_css_path} -o ${npm_config_css_path} --minify", - "build:local": "env FORCE_SHOW_EDIT_PAGE_LINK=true antora --clean --fetch --stacktrace local-preview-playbook.yml" - }, - "dependencies": { - "@antora/atlas-extension": "^1.0.0-alpha.2", - "@antora/collector-extension": "^1.0.0-alpha.3", - "@asciidoctor/tabs": "^1.0.0-beta.6", - "antora": "3.2.0-alpha.4", - "asciidoctor-external-callout": "~1.2.1", - "asciidoctor-kroki": "~0.18.1", - "csv-parser": "^3.0.0", - "lodash": "^4.17.21", - "npm-run-all": "^4.1.5", - "tailwindcss": "^3.3.5" + "build:local": "npm --prefix ../datastax-docs-site run build:partial --build-only=$(basename $(pwd)) --build-local -- antora-playbooks/release.yml --to-dir $(pwd)/build" } }