Add VuePress infrastructure for preview (#870)

This allows a preview VuePress resembling the final
website to be built in order to preview the main
documentation (in the openhab-docs repository, content
fetched from other repos is excluded).

Started to refactor the sidebar navigation items and
scripts processing pages for VuePress compatibility so
they can be maintained in the openhab-docs repository.

Signed-off-by: Yannick Schaus <github@schaus.net>
pull/872/head
Yannick Schaus 2019-01-14 00:00:42 +01:00 committed by GitHub
parent ae90389d40
commit 96c7e24337
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 12647 additions and 0 deletions

5
.gitignore vendored
View File

@ -17,3 +17,8 @@ project.pbxproj
#vscode
.vscode
# Built docs
docs
addons/integrations
vuepress

3
.vuepress/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
addons-*
public/logos
tmp

View File

@ -0,0 +1,28 @@
# This function will add placeholders for pages that are out of scope of the docs preview
def add_placeholder_pages()
puts ">>> Adding placeholder pages for preview"
[
"docs/concepts",
"docs/configuration/iconsets/classic",
"docs/configuration/ui/habmin",
"docs/configuration/ui/habot",
"docs/configuration/ui/basic",
"docs/configuration/ui/basic",
"docs/configuration/ui/classic",
"docs/ecosystem/alexa",
"docs/ecosystem/google-assistant",
"docs/ecosystem/ifttt",
"docs/ecosystem/ifttt",
"docs/ecosystem/mycroft",
"addons/integrations/homekit"
].each { |dir|
puts " -> #{dir}/"
FileUtils.mkdir_p(dir)
File.open("#{dir}/readme.md", "w+") { |f|
f.puts "# This content is unavailable"
f.puts ""
f.puts "This content is migrated from another repository, and is not included in this preview."
}
}
end

View File

@ -0,0 +1,110 @@
<template>
<div class="page-versions">
<div class="dropdown-wrapper" :class="{ open }">
<a class="dropdown-title" @click="toggle">
<span class="title">Version: {{currentVersion}}</span>
<span class="arrow" :class="open ? 'down' : 'right'"></span></span>
</a>
<ul class="nav-dropdown" v-show="open">
<li v-for="version in versions" class="dropdown-item">
<a class="current" v-if="version.number === currentVersion">{{version.number}}</a>
<a v-else :href="version.url">{{version.number}}</a>
</li>
</ul>
</div>
</div>
</template>
<style lang="stylus">
.content:not(.custom)>h1:first-child
margin-right 140px
.page-versions
position absolute
top 5rem
white-space nowrap
right 2rem
font-size 9pt
margin 5px
padding 3px
height 14px
user-select none
.dropdown-wrapper
padding 2px
position absolute
right 0
.dropdown-title
border 1px solid #eee
border-radius 2px
padding 5px
color black
cursor pointer
&:hover
text-decoration none !important
border 1px solid #ccc
.nav-dropdown
box-sizing border-box
max-height calc(100vh - 2.7rem)
overflow-y auto
top 100%
right 0
background-color #fff
padding 10px 0
border 1px solid #ddd
border-bottom-color #ccc
text-align left
border-radius 0.25rem
white-space nowrap
margin 0;
position relative
top 0
.current
color black
font-weight bold !important
&:hover
text-decoration none
color black !important
</style>
<script>
export default {
data () {
return {
versionNumbers: ['latest', '2.4', '2.3', '2.2'], //, '2.1'],
currentVersion: 'latest',
open: false
}
},
methods: {
toggle () {
this.open = !this.open
}
},
created () {
if (this.$site.base && this.$site.base.indexOf('v') > 0) {
this.currentVersion = this.$site.base.replace('v', '').replace(/\//g, '')
this.versionNumbers = ['latest', this.currentVersion] // to avoid having to regenerate previous sites
}
},
computed: {
versions () {
return this.versionNumbers.map(version => {
let url = this.$page.path
if (version === '2.1') {
url = url.replace('addons/integrations/', 'addons/ios/')
if (url.indexOf('/addons') === 0) url += 'readme.html'
}
if (version === 'latest') {
url = 'https://www.openhab.org' + url
} else {
url = `https://${(version === '2.1') ? 'docs.' : 'www.'}openhab.org${version === 'snapshot' ? '' : '/v' + version}${url}`
}
return {
number: version,
url: url
}
})
}
}
}
</script>

View File

@ -0,0 +1,38 @@
<template>
<div class="editLink" v-if="editUrl">
<em>Caught a mistake or want to contribute to the documentation? <a target="_blank" :href="editUrl">Edit this page on GitHub<OutboundLink /></a></em>
<div v-if="isEsh" class="esh-note"><br />
&#128712; This page comes from the Eclipse SmartHome project, which has specific
<a target="_blank" href="https://github.com/eclipse/smarthome/blob/master/CONTRIBUTING.md">legal and technical<OutboundLink /></a>
requirements for accepting contributions, please read them before submitting a change.
</div>
</div>
</template>
<style lang="stylus">
.editLink
border-top 1px solid #eee
padding 1rem
font-size 10pt
margin-bottom -3rem
.esh-note
color #999
font-size 8pt
svg
height: 10px !important
width: 10px !important
</style>
<script>
export default {
computed: {
isEsh () {
return (this.$page.frontmatter.source.indexOf('eclipse/smarthome') > 0)
},
editUrl () {
if (!this.$page || !this.$page.frontmatter.source) return null
return this.$page.frontmatter.source.replace('/blob/', '/edit/').replace('/developer/', '/developers/')
}
}
}
</script>

94
.vuepress/config.js Normal file
View File

@ -0,0 +1,94 @@
const DocsSidebarNavigation = require('./docs-sidebar.js')
const fs = require ('fs-extra')
const path = require('path')
// const CopyWebpackPlugin = require('copy-webpack-plugin')
const HighlightDsl = require('./highlight-dsl')
const HighlightRules = require('./highlight-rules')
const base = process.env.OH_DOCS_VERSION ? `/v${process.env.OH_DOCS_VERSION}/` : '/'
module.exports = {
title: 'Documentation Preview',
description: 'This is a preview of the main parts of the documentation, found in the openhab/openhab-docs repository',
dest: 'vuepress',
host: 'localhost',
base,
shouldPrefetch: () => false,
head: [
['link', { rel: 'stylesheet', href: `/fonts/fonts.css` }],
['link', { rel: 'icon', href: `/favicon.ico` }],
['link', { rel: 'shortcut icon', href: `/favicon.ico` }],
['link', { rel: 'apple-touch-icon', href: `/apple-icon.png` }],
// ['link', { rel: 'stylesheet', href: `https://fonts.googleapis.com/css?family=Open+Sans:300,400` }],
['meta', { property: 'og:type', content: 'website' }],
['meta', { property: 'og:image', content: 'https://www.openhab.org/og-image.png' }],
// ['meta', { property: 'og:title', content: 'openHAB' }],
// ['meta', { property: 'og:description', content: 'a vendor and technology agnostic open source automation software for your home' }],
// ['script', { src: `https://identity.netlify.com/v1/netlify-identity-widget.js` }]
],
markdown: {
config: (md) => {
md.options.linkify = true
const highlight = md.options.highlight
md.options.highlight = (str, lang) => {
/* Simple heuristics to detect rules & other openHAB DSL code snippets and override the language */
if (str.match(/\b(?:Color|Contact|Dimmer|Group|Number|Player|Rollershutter|Switch|Location|Frame|Default|Text|Group|Selection|Setpoint|Slider|Colorpicker|Chart|Webview|Mapview|Image|Video|Item|Thing|Bridge|Time|Type|Sitemap|sitemap)\b/)) {
lang = 'dsl'
}
if (str.match(/\b(?:String|DateTime)\b/) && lang !== 'java' && lang !== 'xml') {
lang = 'dsl'
}
if ((str.match(/\brule\b/) && str.match(/\bwhen\b/) && str.match(/\bthen\b/) && str.match(/\bend\b/)) ||
str.match(/received update/) || str.match(/changed.*(?:from|to)/) || str.match(/Channel.*triggered/) ||
str.match(/\bval\b/) || str.match(/\bvar\b/) /* <-- dangerous! */) {
if (lang !== 'nginx' && lang !== 'shell') lang = 'rules'
}
if (lang === 'shell' || lang === 'sh' || lang === 'shell_session') lang = 'bash'
if (lang === 'conf') lang = 'dsl'
if (lang === 'JSON') lang = 'json'
// if (lang === 'xtend' || lang === 'text' || !lang) {
// console.log('Cannot determine language of code: ' + lang)
// console.log(str)
// }
if (!Prism.languages.dsl || !Prism.languages.rules) {
Prism.languages.dsl = HighlightDsl
Prism.languages.rules = HighlightRules
}
return highlight(str, lang)
}
}
},
// configureWebpack: (config, isServer) => {
// config.plugins.push(new CopyWebpackPlugin([
// { from: '.vuepress/_redirects', to: '.'},
// { from: '.vuepress/_headers', to: '.'},
// ]))
// },
serviceWorker: false,
themeConfig: {
logo: `/openhab-logo.png`,
// repo: 'openhab',
editLinks: false,
activeHeaderLinks: false,
sidebarDepth: 0,
docsDir: 'docs',
nav: [
{
text: 'Documentation',
link: '/docs/',
},
{
text: 'GitHub',
link: 'https://github.com/openhab/openhab-docs',
}
],
sidebar: {
'/docs/': DocsSidebarNavigation.filter((s, i) => s.title !== 'Concepts')
}
}
}

133
.vuepress/docs-sidebar.js Normal file
View File

@ -0,0 +1,133 @@
module.exports = [
{
title: 'Welcome to openHAB',
collapsable: false,
children: [
''
]
},
{
title: 'Concepts',
collapsable: false,
children: [
['concepts/', 'Concepts Overview'],
'concepts/things',
'concepts/items',
'concepts/discovery',
'concepts/audio',
'concepts/units-of-measurement', // from v2.3 onwards
]
},
{
title: 'Installation Guide',
collapsable: false,
children: [
'installation/',
['installation/linux', 'Linux'],
['installation/windows', 'Windows'],
['installation/macos', 'macOS'],
'installation/openhabian',
'installation/rasppi',
'installation/pine',
'installation/docker',
'installation/synology',
'installation/qnap',
['installation/security', 'Security']
]
},
{
title: 'New User Tutorial',
collapsable: false,
children: [
['tutorial/', 'Tutorial Overview'],
'tutorial/1sttimesetup',
'tutorial/uis',
'tutorial/configuration',
'tutorial/sitemap',
'tutorial/rules',
'tutorial/logs',
['tutorial/persistence', 'Persistence']
]
},
{
title: 'Configuration Guide',
collapsable: false,
children: [
['configuration/', 'Configuration Overview'],
'configuration/addons',
'configuration/things',
'configuration/items',
'configuration/sitemaps',
'configuration/persistence',
'configuration/rules-dsl',
'configuration/transformations',
'configuration/actions',
'configuration/iconsets/classic/',
'configuration/jsr223',
'configuration/services',
'configuration/multimedia',
['configuration/migration/', 'Migration from 1.x']
]
},
{
title: 'Interfaces and Ecosystem',
collapsable: false,
children: [
'configuration/packages',
'configuration/editors',
'configuration/homebuilder',
['configuration/paperui', 'Paper UI'],
['configuration/ui/habmin/', 'HABmin'],
['configuration/ui/habot/', 'HABot'],
'configuration/habpanel',
['configuration/ui/basic/', 'Basic UI'],
['configuration/ui/classic/', 'Classic UI'],
'configuration/rules-ng',
'configuration/eclipseiotmarket',
['configuration/restdocs', 'REST API'],
'apps/android',
'apps/ios',
'apps/windows',
['ecosystem/alexa/', 'Amazon Alexa'],
['ecosystem/google-assistant/', 'Google Assistant'], // from v2.3 onwards
['../addons/integrations/homekit/', 'Apple HomeKit'],
['ecosystem/ifttt/', 'IFTTT'],
['ecosystem/mycroft/', 'Mycroft.AI'],
]
},
{
title: 'Administration Guide',
collapsable: false,
children: [
'administration/',
'administration/console',
'administration/runtime',
'administration/bundles',
'administration/logging',
'administration/jsondb',
]
},
{
title: 'Developer Guide',
collapsable: false,
children: [
['developer/', 'Development Overview'],
'developer/contributing/contributing',
'developer/prerequisites/osgi',
'developer/prerequisites/osgids',
'developer/prerequisites/configadmin',
'developer/prerequisites/osgitasks',
'developer/prerequisites/eventadmin',
'developer/prerequisites/tycho',
'developer/prerequisites/equinox',
'developer/prerequisites/targetplatform',
'developer/development/ide',
'developer/development/guidelines',
'developer/development/conventions', // from v2.3 onwards
'developer/development/bindings',
'developer/development/logging',
'developer/development/evolution',
'developer/development/compatibilitylayer',
]
},
]

View File

@ -0,0 +1,35 @@
module.exports = {
'comment': [
{
pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
lookbehind: true
},
{
pattern: /(^|[^\\:])\/\/.*/,
lookbehind: true,
greedy: true
}
],
'string': {
pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
greedy: true
},
'class-name': {
pattern: /(\b(?:Color|Contact|DateTime|Dimmer|Group|Number|Player|Rollershutter|String|Switch|Location|Frame|Default|Text|Group|Selection|Setpoint|Slider|Colorpicker|Chart|Webview|Image|Video|Item|Thing|Bridge|Time|Type)[\w:\(,\)]*\s+)[\w.:\\]+/i,
lookbehind: true,
inside: {
punctuation: /[.:\\]/
}
},
'constant': /\b(?:label|icon|item|mappings|item|minValue|maxValue|step|switchSupport|height|url|refresh|encoding|visibility|period|service|begin|end|legend|labelcolor|valuecolor|AVG|MIN|MAX|SUM|AND|OR|NAND|NOR|EQUAL)\b/,
'keyword': /\b(?:Color|Contact|DateTime|Dimmer|Group|Number|Player|Rollershutter|String|Switch|Location|Frame|Default|Text|Group|Selection|Setpoint|Slider|Colorpicker|Chart|Webview|Mapview|Image|Video|Item|Thing|Bridge|Channels|Time|Type|Sitemap|sitemap|Strategies|Items|Length|Temperature|Pressure|Speed|Intensity|Dimensionless|DimensionLess|Angle|Power|Energy|Illuminance)\b/,
'boolean': /\b(?:true|false)\b/,
'function': /\s<[a-z0-9_]+>/i,
'tag': /\s\([a-z0-9_, ]+\)/i,
'number': /\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp-]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?[df]?/i,
'operator': {
pattern: /(^|[^.])(?:\+[+=]?|-[-=]?|!=?|<<?=?|>>?>?=?|==?|&[&=]?|\|[|=]?|\*=?|\/=?|%=?|\^=?|[?:~])/m,
lookbehind: true
},
'punctuation': /[{}[\];(),.:]/
}

View File

@ -0,0 +1,41 @@
module.exports = {
'comment': [
{
pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
lookbehind: true
},
{
pattern: /(^|[^\\:])\/\/.*/,
lookbehind: true,
greedy: true
}
],
'string': {
pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
greedy: true
},
'class-name': [
{
pattern: /((?:\b(?:instanceof|as|new|val|var)\s+)|(?:catch\s+\())[A-Z][\w.\\]+/,
lookbehind: true,
inside: {
punctuation: /[.\\]/
}
},
{
pattern: /\b((?:import\s+[\w\.]+)\.)[\w.]+\b/,
lookbehind: true
},
],
'constant': /\b(?:INCREASE|DECREASE|NEXT|PREVIOUS|ON|OFF|OPEN|CLOSED|PLAY|PAUSE|REWIND|FASTFORWARD|STOP|MOVE|UP|DOWN|UNDEF|string|int|boolean|long|float|double|short|char|byte|NULL|null)\b/,
'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|import|function|new|try|throw|catch|finally|break|continue|switch|case|default|synchronized|rule|when|Item|Thing|Channel|changed|updated|Time cron|Time is midnight|Time is noon|System started|System shuts down|received update|received command|triggered|from|to|or|as|then|end|var|val)\b/,
'boolean': /\b(?:true|false)\b/,
'function': /(?:\w+(?=\()|toString|getInstance|intValue|doubleValue|floatValue)/,
'function-name': /\b[A-Z][\w_]+(?=\.|:)/,
'number': /\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp-]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?[df]?/i,
'operator': {
pattern: /(^|[^.])(?:\+[+=]?|-[-=]?|!=?|<<?=?|>>?>?=?|==?|&[&=]?|\|[|=]?|\*=?|\/=?|%=?|\^=?|[?:~])/m,
lookbehind: true
},
'punctuation': /[{}[\];(),.:]/
}

4
.vuepress/override.styl Normal file
View File

@ -0,0 +1,4 @@
$accentColor = #ff6600
$MQMobile = 859px
$MQNarrow = 1023px

239
.vuepress/process_file.rb Normal file
View File

@ -0,0 +1,239 @@
# This function converts a "source" file to something looking good in VuePress,
# adding, replacing and stuff
require "fileutils"
require "net/http"
require "uri"
require "rexml/document"
def process_file(indir, file, outdir, source)
in_frontmatter = false
frontmatter_processed = false
has_source = false
has_logo = false
obsolete_binding = false
og_title = 'openHAB'
og_description = 'a vendor and technology agnostic open source automation software for your home'
if !File.exists?("#{indir}/#{file}") then
puts "process_file: IGNORING (NON-EXISTING): #{indir}/#{file}"
return
end
FileUtils.mkdir_p(outdir)
File.open("#{outdir}/#{file}", "w+") { |out|
File.open("#{indir}/#{file}").each { |line|
next if line =~ /^layout: documentation/
next if line =~ /^layout: tutorial/
next if line =~ /^layout: developers/
next if line =~ /^layout: intro/
next if line =~ /^{% include base.html %}/
next if line =~ /\{: #/
next if line =~ /\{::options/
next if line =~ /TOC/
next if line =~ /no_toc/
has_source = true if in_frontmatter && line =~ /^source:/
has_logo = true if in_frontmatter && line =~ /^logo:/
if in_frontmatter && line =~ /^title:/ then
og_title = line.gsub('title: ', '').gsub("\n", "")
end
if in_frontmatter && line =~ /^description:/ then
og_description = line.gsub('description: ', '').gsub("\n", "").gsub('[', '').gsub(']', '').gsub(/\(http[:\/\-0-9A-Za-z\.]+\)/, '')
end
if line =~ /^---$/ then
if !in_frontmatter then
in_frontmatter = true
elsif !frontmatter_processed
if !has_source && source then
# Prefer already present source
out.puts "source: #{source}"
elsif !has_source
# Try to determine the source
outdir_parts = outdir.split('/')
outdir_parts[1] = "binding" if outdir_parts[1] == "bindings"
outdir_parts[1] = "transform" if outdir_parts[1] == "transformations"
outdir_parts[1] = "io" if outdir_parts[1] == "integrations"
if (outdir_parts[0] == "addons") then
addon_type = outdir_parts[1]
addon = file.split('/')[0]
source = ""
if addon == "habmin" then
puts " (add-on is habmin)"
source = "https://github.com/openhab/org.openhab.ui.habmin/blob/master/README.md"
elsif addon == "habpanel" then
puts " (add-on is habpanel)"
source = "https://github.com/openhab/org.openhab.ui.habpanel/blob/master/README.md"
elsif addon == "zigbee" then
puts " (add-on is zigbee)"
source = "https://github.com/openhab/org.openhab.binding.zigbee/blob/master/org.openhab.binding.zigbee/README.md"
elsif addon == "zwave" && !(file =~ /things/) then
puts " (add-on is zwave)"
source = "https://github.com/openhab/org.openhab.binding.zwave/blob/master/README.md"
elsif $esh_features.include?("esh-#{addon_type}-#{addon.gsub('.', '-')}") then
puts " (add-on is from ESH)"
source = "https://github.com/eclipse/smarthome/blob/master/extensions/#{addon_type}/org.eclipse.smarthome.#{addon_type}.#{addon}/README.md"
elsif !(file =~ /things/) then
puts " (add-on is from openhab2-addons)"
source = "https://github.com/openhab/openhab2-addons/blob/master/addons/#{addon_type}/org.openhab.#{addon_type}.#{addon}/README.md"
end
out.puts "source: #{source}" if source != ""
# For sub-bundles, set the "prev" link to the main add-on
out.puts "prev: ../#{addon.split('.')[0]}/" if addon.include?('.')
# Prev link to the main binding doc for zwave/doc/things.md
out.puts "prev: ../" if file == 'zwave/doc/things.md'
end
end
# Add OpenGraph tags
out.puts "meta:"
out.puts " - property: og:title"
out.puts " content: \"#{og_title.gsub('"', '\"')}\""
out.puts " - property: og:description"
out.puts " content: #{og_description}"
in_frontmatter = false
frontmatter_processed = true
end
end
# Replace the Jekyll "contribution wanted" include file by custom VuePress markup
line = "[[toc]]" if line =~ /\{:toc/
if line =~ /\{% include contribution-wanted.html %\}/
out.puts "::: tip Contribution Wanted"
out.puts "Please help us improve the documentation! "
out.puts "If you'd like to leave corrections, additions or comments for this article or any other part of this website, please drop a word at:"
out.puts "[Documentation Issue Tracker](#{$docs_repo}/issues)"
out.puts ":::"
next
end
# Actions and transformations are currently partly in add-ons, copy the content above the list of add-ons
break if line =~ /^More details regarding this and other Transformation services can be found in the individual transformation articles linked below./
break if line =~ /^## Installable Actions/
# Remove collapsibles in Linux install document and replace them by regular headings
next if line =~ /include collapsible/ && file =~ /linux/
line = "##### " + line if line =~ /^Apt Based Systems/ && file =~ /linux/
line = "##### " + line if line =~ /^Yum or Dnf Based Systems/ && file =~ /linux/
line = "##### " + line if line =~ /^Systems based on/ && file =~ /linux/
# Fix headers for some pages
line = line.gsub(/^##/, "#") if (outdir == "docs/configuration/ui" && (file =~ /basic/ || file =~ /classic/)) || file == 'astro1/readme.md'
# Fix broken links in the package selection article
if outdir == 'docs/configuration' && file =~ /packages/ then
line = line.gsub('(../addons/uis/paper/readme.html)', '(paperui.html)')
line = line.gsub('(../addons/uis/basic/readme.html)', '(ui/basic/)')
line = line.gsub('(../addons/uis/classic/readme.html)', '(ui/classic/)')
line = line.gsub('(../addons/uis/habmin/readme.html)', '(ui/habmin/)')
line = line.gsub('(../addons/uis/habpanel/readme.html)', '(habpanel.html)')
end
# Handle obsolete bindings
if in_frontmatter && (line =~ /label: / || line =~ /title: /) && outdir == 'addons/bindings' && file =~ /1\// then
addon = file.split('/')[0]
if !$ignore_bindings.include?(addon.gsub('1', '')) && Dir.exists?("#{indir}/#{addon.gsub('1', '')}") then
line = line.gsub("\n", "") + ' (1.x)' if !(line =~ /1\.x/)
if !obsolete_binding then
obsolete_binding = true
out.puts "obsolete: true"
puts " obsolete!"
end
end
end
if !in_frontmatter && line =~ /^# / then
# Put a warning banner for obsolete bindings
out.puts line
if obsolete_binding then
out.puts
out.puts "::: danger OBSOLETE BINDING"
new_addon = file.split('/')[0].gsub('1', '')
out.puts "This 1.x binding is obsolete; it has been replaced by the 2.x [#{new_addon}](../#{new_addon}/) binding which you should use instead."
out.puts ":::"
out.puts
obsolete_binding = false
end
# Add the logo if specified
if has_logo then
out.puts
out.puts '<AddonLogo/>'
has_logo = false
end
next
end
# Expand <!--list-subs--> comments with a list of links
# (https://github.com/eclipse/smarthome/issues/5571)
if line =~ /<!--\s*list-subs\s*-->/ then
sub_addons = get_subs_links(file.split('/')[0], indir)
out.puts
sub_addons.each { |sub|
out.puts "- [#{sub[1]}](../#{sub[0]}/)"
}
out.puts
end
# Replace links to generated docs in ZWave's things.md by links to the internal viewer
line = line.gsub(/]\((.*)\/(.*)\)/, '](../thing.html?manufacturer=\1&file=\2)') if file == 'zwave/doc/things.md'
# Misc replaces (relative links, remove placeholder interpreted as custom tags)
line = line.gsub('http://docs.openhab.org/addons/uis/paper/readme.html', '/docs/configuration/paperui.html')
line = line.gsub('http://docs.openhab.org/addons/uis/habpanel/readme.html', '/docs/configuration/habpanel.html')
line = line.gsub('http://docs.openhab.org/addons/uis/habmin/readme.html', '/docs/configuration/habmin.html')
line = line.gsub('http://docs.openhab.org/addons/uis/basic/readme.html', '/docs/configuration/ui/basic/')
line = line.gsub(/http:\/\/docs\.openhab\.org\/addons\/(.*)\/(.*)\/readme\.html/, '/addons/\1/\2/')
line = line.gsub('http://docs.openhab.org/', '/docs/')
line = line.gsub('/addons/io/', '/addons/integrations/')
line = line.gsub("{{base}}/", "./docs/")
line = line.gsub("{{docu}}/", "./docs/")
line = line.gsub("(images/", "(./images/")
line = line.gsub("src=\"images/", "src=\"./images/")
line = line.gsub("]:images/", "]:./images/")
line = line.gsub("](doc/", "](./doc/")
line = line.gsub("(diagrams/", "(./diagrams/")
line = line.gsub("./docs/tutorials/beginner/", "/docs/tutorial/")
line = line.gsub("./docs/", "/docs/")
line = line.gsub("<activeState>", '\<activeState\>')
line = line.gsub("<passiveState>", '\<passiveState\>')
line = line.gsub("<dimension>", '\<dimension\>')
line = line.gsub("<TransformProgram>", '\<TransformProgram\>')
line = line.gsub("<FlahshbriefingDeviceID>", '`<FlahshbriefingDeviceID>`') if file =~ /amazonechocontrol/
line = line.gsub("<SerialNumber>", '&lt;SerialNumber&gt;') if file =~ /airvisualnode/
line = line.gsub("<version>", '&lt;version&gt;') if file =~ /caldav/
line = line.gsub("by <step>", 'by `<step>`') if file =~ /ipx8001/
line = line.gsub("<BR>", '<BR/>')
line = line.gsub("'<package name>:<widget ID>'", '`<package name>:<widget ID>`') if file =~ /lametrictime/
line = line.gsub("<mac address of bridge>", '`<mac address of bridge>`') if file =~ /milight/
line = line.gsub("<mac>", '`<mac>`') if file =~ /milight/
line = line.gsub("<type of bulb>", '`<type of bulb>`') if file =~ /milight/
line = line.gsub("<IP-Address of bridge>", '`<IP-Address of bridge>`') if file =~ /milight/
line = line.gsub("<bulb>", '`<bulb>`') if file =~ /milight/
line = line.gsub("<zone>", '`<zone>`') if file =~ /milight/
line = line.gsub("[](", '[here](') if file =~ /powermax1/
line = line.gsub("<n>", '&lt;n&gt;') if file =~ /rfxcom/
line = line.gsub(" <value> ", ' &lt;value&gt; ') if file =~ /zibase/
line = line.gsub("<username>", '&lt;username&gt;') if file =~ /zoneminder/
line = line.gsub("<password>", '&lt;password&gt;') if file =~ /zoneminder/
line = line.gsub("<yourzmip>", '&lt;yourzmip&gt;') if file =~ /zoneminder/
line = line.gsub(" <chatId> ", ' &lt;chatId&gt; ') if file =~ /telegram/
line = line.gsub(" <token> ", ' &lt;token&gt; ') if file =~ /telegram/
line = line.gsub("<regular expression>", '\<regular expression\>')
line = line.gsub('src="images/', 'src="./images/') if outdir =~ /apps/
line = line.gsub('](/images/', '](./images/') if outdir =~ /google-assistant/
line = line.gsub(/\{:(style|target).*\}/, '') # Jekyll inline attributes syntax not supported
out.puts line
}
# Add the components for the versions dropdown and the edit link
out.puts
out.puts '<DocPreviousVersions/>' unless file == "introduction.md" and outdir == "docs"
out.puts '<EditPageLink/>'
}
end

View File

@ -0,0 +1,144 @@
require_relative "./process_file.rb"
def process_main_docs(docs_source_dir)
puts ">>> Migrating the introduction article"
process_file(".", "introduction.md", "docs", "https://github.com/openhab/openhab-docs/blob/master/introduction.md")
FileUtils.mv("docs/introduction.md", "docs/readme.md")
puts ">>> Migrating common images"
FileUtils.mkdir_p("docs/images")
FileUtils.cp_r("#{docs_source_dir}/images/distro.png", "docs/images")
FileUtils.cp_r("#{docs_source_dir}/images/dashboard.png", "docs/images")
puts ">>> Migrating logos"
FileUtils.cp_r("#{docs_source_dir}/images/addons", ".vuepress/public/logos")
puts ">>> Migrating the Concepts section"
if Dir.exists?("#{docs_source_dir}/concepts") then
Dir.glob("#{docs_source_dir}/concepts/*.md").each { |path|
file = File.basename(path)
next if file == "categories.md"
puts " -> #{file}"
process_file("#{docs_source_dir}/concepts", file, "docs/concepts", "#{$esh_repo_root}/concepts/#{file}")
}
puts " -> images and diagrams"
FileUtils.cp_r("#{docs_source_dir}/concepts/images", "docs/concepts/images")
FileUtils.cp_r("#{docs_source_dir}/concepts/diagrams", "docs/concepts/diagrams")
else
puts " Skipping non-existing section!"
end
puts ">>> Migrating the Installation section"
Dir.glob("#{docs_source_dir}/installation/*.md") { |path|
file = File.basename(path)
next if file == "designer.md"
puts " -> #{file}"
process_file("#{docs_source_dir}/installation", file, "docs/installation", "#{$docs_repo_root}/installation/#{file}")
}
puts " -> images"
FileUtils.cp_r("#{docs_source_dir}/installation/images", "docs/installation/images")
puts ">>> Migrating the Tutorial section"
Dir.glob("#{docs_source_dir}/tutorials/beginner/*.md") { |path|
file = File.basename(path)
puts " -> #{file}"
process_file("#{docs_source_dir}/tutorials/beginner", file, "docs/tutorial", "#{$docs_repo_root}/tutorials/beginner/#{file}")
}
puts " -> images"
FileUtils.cp_r("#{docs_source_dir}/tutorials/beginner/images", "docs/tutorial/images")
# FileUtils.cp_r("#{docs_source_dir}/tutorials/images/*", "docs/tutorial/images")
puts ">>> Migrating the Configuration section"
Dir.glob("#{docs_source_dir}/configuration/*.md") { |path|
file = File.basename(path)
next if file == "transform.md" # Useless, copy the one from addons
puts " -> #{file}"
process_file("#{docs_source_dir}/configuration", file, "docs/configuration", "#{$docs_repo_root}/configuration/#{file}")
}
puts " -> images"
FileUtils.cp_r("#{docs_source_dir}/configuration/images", "docs/configuration")
process_file("#{docs_source_dir}/addons", "actions.md", "docs/configuration", "#{$docs_repo_root}/addons/actions.md")
process_file("#{docs_source_dir}/addons", "transformations.md", "docs/configuration", "#{$docs_repo_root}/addons/transformations.md")
process_file("#{docs_source_dir}/tutorials", "migration.md", "docs/configuration/migration", "#{$docs_repo_root}/tutorials/migration.md")
FileUtils.mv("docs/configuration/migration/migration.md", "docs/configuration/migration/index.md")
FileUtils.cp_r("#{docs_source_dir}/tutorials/images", "docs/configuration/migration")
puts ">>> Migrating the UI section"
Dir.glob("#{docs_source_dir}/_addons_uis/**") { |path|
next if path =~ /habpanel/ || path =~ /paper/ # Those already have their own article, no need to include the readme...
addon = File.basename(path)
puts " -> #{addon}"
FileUtils.mkdir_p("docs/configuration/ui/" + addon)
process_file("#{docs_source_dir}/_addons_uis", addon + "/readme.md", "docs/configuration/ui", "")
puts " -> images (#{addon})"
FileUtils.cp_r("#{docs_source_dir}/_addons_uis/#{addon}/doc", "docs/configuration/ui/#{addon}") if Dir.exists?("#{docs_source_dir}/_addons_uis/#{addon}/doc")
}
puts ">>> Migrating the Apps section"
Dir.glob("#{docs_source_dir}/addons/uis/apps/*.md") { |path|
file = File.basename(path)
puts " -> #{file}"
process_file("#{docs_source_dir}/addons/uis/apps", file, "docs/apps", "#{$docs_repo_root}/addons/uis/apps/#{file}")
}
puts " -> images"
FileUtils.cp_r("#{docs_source_dir}/addons/uis/apps/images", "docs/apps")
puts ">>> Migrating the Administration section"
Dir.glob("#{docs_source_dir}/administration/*.md") { |path|
file = File.basename(path)
puts " -> #{file}"
process_file("#{docs_source_dir}/administration", file, "docs/administration", "#{$docs_repo_root}/administration/#{file}")
}
puts " -> images"
FileUtils.cp_r("#{docs_source_dir}/administration/images", "docs/administration/images")
puts ">>> Migrating the Developer section"
process_file("#{docs_source_dir}/developers", "index.md", "docs/developer", "#{$docs_repo_root}/developer/index.md")
["prerequisites", "development", "contributing"].each { |subsection|
Dir.glob("#{docs_source_dir}/developers/#{subsection}/*.md") { |path|
file = File.basename(path)
puts " -> #{subsection}/#{file}"
process_file("#{docs_source_dir}/developers/#{subsection}", file, "docs/developer/#{subsection}", "#{$docs_repo_root}/developer/#{subsection}/#{file}")
}
if subsection != "contributing" then
puts " -> #{subsection}/images"
FileUtils.cp_r("#{docs_source_dir}/developers/#{subsection}/images", "docs/developer/#{subsection}")
end
}
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

1
.vuepress/public/cookieinfo.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -0,0 +1,34 @@
/* Open Sans font weights 300-400 */
/* latin-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 300;
src: local('Open Sans Light'), local('OpenSans-Light'), url(/fonts/mem5YaGs126MiZpBA-UN_r8OXOhpOqc.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 300;
src: local('Open Sans Light'), local('OpenSans-Light'), url(/fonts/mem5YaGs126MiZpBA-UN_r8OUuhp.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(/fonts/mem8YaGs126MiZpBA-UFW50bbck.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(/fonts/mem8YaGs126MiZpBA-UFVZ0b.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

107
.vuepress/style.styl Normal file
View File

@ -0,0 +1,107 @@
.navbar:not(.headroom--top):not(.transparent)
box-shadow rgba(10%,10%,10%,25%) 0 0 10px
background-color rgba(98%, 98%, 99%, 0.9) // linear-gradient(180deg,hsla(0,0%,100%,.3),hsla(0,0%,100%,.3) 95%,rgba(0,0,0,.05) 99%,rgba(0,0,0,.04))
.homepage
.navbar:not(.headroom)
opacity 0
background transparent
color white
border-bottom none
box-shadow none
.logo
opacity 0
.nav-dropdown
color black
.nav-links > .nav-item:last-child
svg
color white
.dropdown-title .arrow
border-top 6px solid #fff
.navbar
.links
background-color transparent !important
.nav-dropdown
// background-color white
background-color rgba(98%, 98%, 99%, 0.96) !important
box-shadow rgba(10%,10%,10%,25%) 0 0 5px
.nav-item a
// font-family 'Open Sans', sans-serif
font-weight 400
font-size 1rem
.dropdown-subitem .nav-link a
font-weight normal
// not for docs preview!
// .site-name
// display none
.dropdown-wrapper .nav-dropdown .dropdown-item h4
margin-bottom .2rem
.sidebar
background-color #f7f7f7 !important
// background linear-gradient(90deg, #fff0e0, #fff) !important
@media (min-width: 719px)
.nav-item > a:hover, .nav-item > a.router-link-active
border-bottom 3px solid $accentColor
@media (min-width: 720px) and (max-width: 1023px)
.search-box input:focus
width: 10.8rem // to cover the openHAB text (leaving the logo)
@media (min-width: 1024px) and (max-width: 1280px)
.search-box input
width: 5.7rem
@media (max-width: 360px)
.search-box input:focus
width: 9.4rem // to cover the openHAB text (leaving the logo)
@media (max-width: 419px)
.search-box input:focus
width: 4rem
.content:not(.custom)>h1:first-child
font-family 'Open Sans', sans-serif
font-weight 400
@media print
.navbar
display none
.page-versions
display none
.page-nav
display none
.editLink
display none
.content pre
overflow hidden !important
white-space pre-wrap !important
.content:not(.custom), .page-nav
max-width 1280px !important
.page .content:not(.custom):not(.page-nav):not(.edit-link)
min-height 85vh !important
.page .content.edit-link
display none
.logo
width 160px
height 35px
a[href*='.openhab.org'] .outbound
display none
.nav-item > a.external:hover
border-bottom 2px solid #ff7214
.custom-block.tip
border-color #2196f3 !important

11561
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

24
package.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "openhab-docs",
"version": "1.0.0",
"description": "openHAB Documentation",
"main": "index.js",
"scripts": {
"prepare-docs": "ruby prepare-docs.rb",
"build-preview": "ruby prepare-docs.rb --delete-sources && vuepress build .",
"build-only": "vuepress build ."
},
"repository": {
"type": "git",
"url": "git+https://github.com/openhab/openhab-docs.git"
},
"author": "",
"license": "EPL-1.0",
"bugs": {
"url": "https://github.com/openhab/openhab-docs/issues"
},
"homepage": "https://github.com/openhab/openhab-docs#readme",
"dependencies": {
"vuepress": "^0.14.8"
}
}

46
prepare-docs.rb Normal file
View File

@ -0,0 +1,46 @@
# This will clone https://github.com/openhab/openhab-docs
# and migrate content into the website with some changes
require "fileutils"
require "net/http"
require "uri"
require "rexml/document"
# require "nokogiri"
$docs_repo = "https://github.com/openhab/openhab-docs"
$docs_repo_root = $docs_repo + "/blob/master"
$docs_repo_branch = "final"
$esh_repo = "https://github.com/eclipse/smarthome"
$esh_repo_root = $esh_repo + "/blob/master/docs/documentation"
$version = nil
require_relative "./.vuepress/process_file.rb"
require_relative "./.vuepress/process_main_docs.rb"
require_relative "./.vuepress/add_placeholders.rb"
if (Dir.exists?("docs")) then
puts ">>> Removing processed docs"
FileUtils.rm_rf("docs")
end
if (Dir.exists?("addons/integrations")) then
puts ">>> Removing processed addons"
FileUtils.rm_rf("docs")
end
process_main_docs(".")
add_placeholder_pages()
if (ARGV[0] && ARGV[0] == "--delete-sources") then
puts ">>> !!! Deleting source files - for ephemeral clones only!"
["administration", "appendix", "community", "configuration", "developers", "installation", "tutorials"].each { |d|
FileUtils.rm_rf(d)
}
end
# Regenerate the classic iconset docs
#puts ">>> Generating iconset"
#system("ruby generate_iconset_doc.rb #{docs_source_dir}/_addons_iconsets classic #{docs_source_dir}/_data docs/configuration/iconsets")