├── .gitignore ├── .npmignore ├── README.md ├── _i18n └── en.json ├── _layouts └── website │ ├── layout.html │ └── page.html ├── package.json └── src └── less ├── panel.less ├── search.less ├── variables.less └── website.less /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Deployed apps should consider commenting this line out: 24 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 25 | node_modules 26 | 27 | # vim swapfile 28 | *.swp 29 | 30 | _assets 31 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Allow _assets folder 2 | !_assets 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitBook FAQ Theme 2 | 3 | Theme for using GitBook to publish an FAQ or Knowledge Base. This theme works perfectly with search plugins (as the [default one](https://github.com/GitbookIO/plugin-search) or [algolia](https://github.com/GitbookIO/plugin-algolia)). 4 | 5 | ## Usage 6 | 7 | This theme requires GitBook version 3 or later. 8 | 9 | Add the theme to your book's configuration (`book.json`): 10 | 11 | ```js 12 | { 13 | "plugins": [ 14 | "theme-faq", 15 | "-fontsettings", 16 | "-sharing" 17 | ] 18 | } 19 | ``` 20 | 21 | **NOTE** `theme-faq` is not compatible with plugins that modify the toolbar (since there is no toolbar). Embedded search will not work as a result. This includes the default plugins `fontsettings` and `sharing` that need to be disabled explicitly (add a minus flag "-" before each plugin parameter). 22 | 23 | ### Add relations between articles 24 | 25 | Suggestions for other articles can be shown at the bottom of an article. 26 | 27 | Relationships are specified in the YAML frontmatter of a page: 28 | 29 | ```md 30 | --- 31 | related: 32 | - some/other/page.md 33 | - another_related_article.md 34 | 35 | --- 36 | 37 | Content of my article! 38 | ``` 39 | 40 | ### Add logo to header 41 | 42 | Extend the theme by creating a file `_layouts/website/page.html` in your book with: 43 | 44 | ```html 45 | {% extends template.self %} 46 | 47 | {% block faq_header_brand %} 48 | 49 | {% endblock %} 50 | ``` 51 | 52 | ### Add navigation links to the header 53 | 54 | Extend the theme by creating a file `_layouts/website/page.html` in your book with: 55 | 56 | ```html 57 | {% extends template.self %} 58 | 59 | {% block faq_menu %} 60 | 64 | {% endblock %} 65 | ``` 66 | 67 | ### Add a short description on the home page 68 | 69 | The content of your `README` is used as a short description for the home page of your FAQ. 70 | 71 | If you wish use a specific file for this description instead of your project's README, you can configure your `book.json` to do so: 72 | 73 | ```json 74 | { 75 | "structure": { 76 | "readme": "home-page-description.md" 77 | } 78 | } 79 | ``` 80 | -------------------------------------------------------------------------------- /_i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "DEFAULT_TITLE": "Help Center", 3 | "FAQ_RELATED_ARTICLES": "Related Articles", 4 | "FAQ_TITLE": "FAQ", 5 | "GITBOOK_LINK": "Published with GitBook", 6 | "SEARCH_PLACEHOLDER": "Have a question? Ask or enter a search term here.", 7 | "SEARCH_RESULTS_TITLE": " results for \"\"", 8 | "SEARCH_NO_RESULTS_TITLE": "No results matching \"\"" 9 | } -------------------------------------------------------------------------------- /_layouts/website/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block head %} 4 | {{ super() }} 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% endblock %} 12 | 13 | {% block style %} 14 | 18 | 22 | 23 | {{ super() }} 24 | {% for type, style in config.styles %} 25 | {% if fileExists(style) and type == "website" %} 26 | 27 | {% endif %} 28 | {% endfor %} 29 | {% endblock %} 30 | 31 | {% block body %} 32 | 51 | 52 |
53 |
54 |

55 | {% block faq_header_title %} 56 | {% if file.path == readme.file.path %} 57 | {{ config.title|d("DEFAULT_TITLE"|t, true) }} 58 | {% else %} 59 | {{ page.title }} 60 | {% endif %} 61 | {% endblock %} 62 |

63 | 64 | {% block search_input %}{% endblock %} 65 | 66 | {% if file.path == readme.file.path %} 67 |
68 | {{ page.content | safe }} 69 |
70 | {% endif %} 71 |
72 |
73 | 74 |
75 | {% block search_results %} 76 | {% block page %}{% endblock %} 77 | 78 | {% block faq_footer %} 79 | 83 | {% endblock %} 84 | {% endblock %} 85 |
86 | {% endblock %} 87 | 88 | 89 | {% block javascript %} 90 | 91 | {% for resource in plugins.resources.js %} 92 | {% if resource.url %} 93 | 94 | {% else %} 95 | 96 | {% endif %} 97 | {% endfor %} 98 | 103 | 104 | {% endblock %} 105 | -------------------------------------------------------------------------------- /_layouts/website/page.html: -------------------------------------------------------------------------------- 1 | {% extends "website/layout.html" %} 2 | 3 | {% block title %} 4 | {% if file.path == readme.file.path %} 5 | {{ config.title|d("DEFAULT_TITLE"|t, true) }} 6 | {% else %} 7 | {{ page.title }} · {{ super() }} 8 | {% endif %} 9 | {% endblock %} 10 | {% block description %}{{ page.description }}{% endblock %} 11 | 12 | {% block page %} 13 | {% if file.path == readme.file.path %} 14 | {% for part in summary.parts %} 15 |
16 |
17 |

18 | {{ (part.articles.length - 1) if (loop.index == 1) else part.articles.length }} articles 19 | {{ part.title }} 20 |

21 |
22 |
23 | {% for article in part.articles %} 24 | {% if article.path != readme.file.path %} 25 | 26 | {{ article.title }} 27 | 28 | {% endif %} 29 | {% endfor %} 30 |
31 |
32 | {% endfor %} 33 | {% else %} 34 |
35 |
36 | 47 |
48 | {{ page.content|safe }} 49 |
50 |
51 |
52 | 53 | {% block faq_page_related %} 54 | {% if page.related.length > 0 %} 55 |
56 |
57 |

{{ "FAQ_RELATED_ARTICLES"|t }}

58 |
59 |
60 | {% for related in page.related %} 61 | {% set relatedArticle = getArticleByPath(related) %} 62 | {% if relatedArticle %} 63 | {{ relatedArticle.title }} 64 | {% endif %} 65 | {% endfor %} 66 |
67 |
68 | {% endif %} 69 | {% endblock %} 70 | {% endif %} 71 | {% endblock %} 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitbook-plugin-theme-faq", 3 | "description": "Theme for using GitBook as a FAQ or Knowledge base", 4 | "version": "1.2.1", 5 | "engines": { 6 | "gitbook": ">=3.0.0-pre.10" 7 | }, 8 | "devDependencies": { 9 | "gitbook-markdown-css": "^1.0.1", 10 | "less": "^2.7.1", 11 | "less-plugin-clean-css": "^1.5.1" 12 | }, 13 | "scripts": { 14 | "prepublish": "mkdir -p _assets/website; lessc -clean-css ./src/less/website.less _assets/website/style.css" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/GitbookIO/theme-faq.git" 19 | }, 20 | "author": "FriendCode Inc. ", 21 | "license": "Apache-2.0", 22 | "bugs": { 23 | "url": "https://github.com/GitbookIO/theme-faq/issues" 24 | }, 25 | "contributors": [ 26 | { 27 | "name": "Samy Pessé", 28 | "email": "samy@gitbook.com" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /src/less/panel.less: -------------------------------------------------------------------------------- 1 | 2 | .panel { 3 | border-radius: 0px; 4 | 5 | .panel-heading { 6 | background: transparent; 7 | border-bottom: 0px; 8 | } 9 | 10 | .panel-title { 11 | text-transform: uppercase; 12 | 13 | .title-secondary { 14 | float: right; 15 | font-size: 12px; 16 | font-weight: 400; 17 | color: #999; 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/less/search.less: -------------------------------------------------------------------------------- 1 | #book-search-input { 2 | margin-top: 30px; 3 | 4 | input { 5 | padding: 8px 10px; 6 | width: @faq-search-width; 7 | min-width: @faq-search-minwidth; 8 | border-radius: 0px; 9 | border: 1px solid #e1e1e1; 10 | outline: none; 11 | box-shadow: none; 12 | font-size: 16px; 13 | 14 | &:focus, &:active { 15 | outline: none; 16 | } 17 | } 18 | } 19 | 20 | .search-results { 21 | padding: @faq-page-padding; 22 | border: 1px solid @header-border; 23 | background: #fff; 24 | 25 | .has-results { 26 | .search-results-title { 27 | margin-top: 0px; 28 | font-size: 16px; 29 | margin-bottom: 20px; 30 | border-bottom: 1px solid #eee; 31 | padding-bottom: 10px; 32 | font-weight: normal; 33 | } 34 | } 35 | 36 | .no-results { 37 | text-align: center; 38 | padding: 40px 0px; 39 | } 40 | } 41 | 42 | @media (max-width: 600px) { 43 | #book-search-input input { 44 | width: 100%; 45 | min-width: 100%; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/less/variables.less: -------------------------------------------------------------------------------- 1 | // Sizes of page content 2 | @faq-page-width: 800px; 3 | @faq-page-padding: 20px; 4 | 5 | // Size of main container 6 | @faq-page-container-width: (@faq-page-width + 2*@faq-page-padding); 7 | 8 | // Search 9 | @faq-search-width: 50%; 10 | @faq-search-minwidth: 400px; 11 | -------------------------------------------------------------------------------- /src/less/website.less: -------------------------------------------------------------------------------- 1 | @import "../../node_modules/gitbook-markdown-css/less/mixin.less"; 2 | 3 | @import "./variables.less"; 4 | @import "./panel.less"; 5 | @import "./search.less"; 6 | 7 | @header-background: #f8f8f8; 8 | @header-border: #e7e7e7; 9 | 10 | .faq-navbar { 11 | margin: 0px; 12 | border: 0px; 13 | } 14 | 15 | .faq-header { 16 | padding: 50px 0px; 17 | padding-bottom: 80px; 18 | 19 | text-align: center; 20 | background-color: @header-background; 21 | border-bottom: 1px solid @header-border; 22 | margin: 0px; 23 | margin-bottom: 30px; 24 | 25 | h1 { 26 | border: 0px; 27 | } 28 | 29 | .description { 30 | color: #777; 31 | text-align: justify; 32 | line-height: 1.8em; 33 | 34 | // Align with faq-page-container 35 | max-width: @faq-page-container-width; 36 | margin: 0px auto; 37 | padding-left: @faq-page-padding; 38 | padding-right: @faq-page-padding; 39 | padding-top: 40px; 40 | } 41 | } 42 | 43 | .faq-page-container { 44 | width: 100%; 45 | max-width: @faq-page-container-width; 46 | margin: 0px auto; 47 | margin-top: -60px; 48 | padding: 0px @faq-page-padding; 49 | margin-bottom: 30px; 50 | } 51 | 52 | .faq-page { 53 | font-size: 15px; 54 | line-height: 1.6; 55 | 56 | .gitbook-markdown(); 57 | } 58 | 59 | .faq-page-footer { 60 | padding: 0px 10px; 61 | margin-bottom: 20px; 62 | text-align: right; 63 | color: #999; 64 | 65 | a, span { 66 | color: inherit; 67 | } 68 | } 69 | 70 | @media (max-width: @faq-page-container-width) { 71 | .faq-header .description { 72 | padding-left: 0px; 73 | padding-right: 0px; 74 | } 75 | 76 | .faq-page-container { 77 | padding: 20px 0px; 78 | 79 | > .panel { 80 | border-right: 0px; 81 | border-left: 0px; 82 | } 83 | } 84 | } 85 | 86 | --------------------------------------------------------------------------------