site-content/lib/tabs-block.js (48 lines of code) (raw):

/* Copyright (c) 2018 OpenDevise, Inc. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * Extends the AsciiDoc syntax to support a tabset. The tabset is created from * a dlist enclosed in an example block that is marked with the tabs style. * * Usage: * * [tabs] * ==== * Tab A:: * + * -- * Contents of tab A. * -- * Tab B:: * + * -- * Contents of tab B. * -- * ==== * * @author Dan Allen <dan@opendevise.com> */ const IdSeparatorCh = '-' const ExtraIdSeparatorsRx = /^-+|-+$|-(-)+/g const InvalidIdCharsRx = /[^a-zA-Z0-9_]/g const List = Opal.const_get_local(Opal.module(null, 'Asciidoctor'), 'List') const ListItem = Opal.const_get_local(Opal.module(null, 'Asciidoctor'), 'ListItem') const generateId = (str, idx) => `tabset${idx}_${str.toLowerCase().replace(InvalidIdCharsRx, IdSeparatorCh).replace(ExtraIdSeparatorsRx, '$1')}` function tabsBlock () { this.onContext('example') this.process((parent, reader, attrs) => { const createHtmlFragment = (html) => this.createBlock(parent, 'pass', html) const tabsetIdx = parent.getDocument().counter('idx-tabset') const nodes = [] nodes.push(createHtmlFragment('<div class="tabset is-loading">')) const container = this.parseContent(this.createBlock(parent, 'open'), reader) const sourceTabs = container.getBlocks()[0] if (!(sourceTabs && sourceTabs.getContext() === 'dlist' && sourceTabs.getItems().length)) return const tabs = List.$new(parent, 'ulist') tabs.addRole('tabs') const panes = {} sourceTabs.getItems().forEach(([[title], details]) => { const tab = ListItem.$new(tabs) tabs.$append(tab) const id = generateId(title.getText(), tabsetIdx) tab.text = `[[${id}]]${title.text}` let blocks = details.getBlocks() const numBlocks = blocks.length if (numBlocks) { if (blocks[0].context === 'open' && numBlocks === 1) blocks = blocks[0].getBlocks() panes[id] = blocks.map((block) => (block.parent = parent) && block) } }) nodes.push(tabs) nodes.push(createHtmlFragment('<div class="content">')) Object.entries(panes).forEach(([id, blocks]) => { nodes.push(createHtmlFragment(`<div class="tab-pane" aria-labelledby="${id}">`)) nodes.push(...blocks) nodes.push(createHtmlFragment('</div>')) }) nodes.push(createHtmlFragment('</div>')) nodes.push(createHtmlFragment('</div>')) parent.blocks.push(...nodes) }) } function register (registry, context) { registry.block('tabs', tabsBlock) } module.exports.register = register