Skip to content

Commit

Permalink
Documentation (#928)
Browse files Browse the repository at this point in the history
* markdownify docs (#714)

* convert all packages

* script to convert scss docs to md files

* remove Weights, convert to `@#+`

* add pages for common files

* add `@page` roots

* 4-space md files (mostly for source)

* remove some `parent` front matters

* remove docs from .scss except markup & modifiers

* [DM] forms docs nesting fixes (#755)

* all files should start with `@#`
depth is computed at layout time

* split controls.md into three files
so they all show up in nav

* textarea gets its own file

* add tsx syntax hints to code blocks

* [DM] Documentalist! (#756)

- 🎆 replace KSS with Documentalist
- 🔨 replace both `docs-interfaces` and `docs-kss` gulp tasks with `docs-json`
- ♻️ refactor docs app to use DM: on its way to being a sweet React theme
  - write a bunch of tag handlers
  - delete `Section` component entirely, replaced with minimal `Page` SFC
  - best scrollspy implementation yet! it's smooth as silk and never glitches out (only known issue is short final sections are hard to highlight)
- 🌲 generate layout tree (for nav) in gulp task
  - requires some nasty rewriting of references 😢
  - but hey it works really well!

* fix duplicate typography.dark-theme key warning

* Tabs2 docs in new page

_really_ deprecate Tabs components

* write components.md

* nav only shows heading links when on that page

* only scroll nav menu if active item is not visible

* fix hotkey headings depth

* 🐛 only scroll to heading when page changes
otherwise scrolling up is damn near impossible!

* delete KSS docs from common/ files
already migrated to markdown in docs/

* restore Progress pages (bar/spinner/skeleton)

decided simplest approach was a mostly empty root `progress` page
that links to the other three.

* fix slider duplicate key warning with new range-slider page

decided not to create two child pages so Single Slider is on the
root Sliders page. not sure about this pattern...

* delete _tabs2.scss (docs only) and fix one code sample

* [DM] KSS for CSS examples (#813)

* update scss & md docs files
- **scss files:** make them all valid KSS blocks again by adding header and reference.
references are now reflective of the CSS class being documented.
- **md files:** add `@css reference` tags in all the CSS API sections
* documentalist@0.0.3
* css tag handler brings back markup & modifiers!
* ♻️ major refactor to sections.scss
a new function `reference()` to target these new KSS examples. refactored as many selectors as I could, and removed a bunch of obsolete ones.

docs changes:
* move checkbox "Inline controls" section
* bring back button-group page, unwrap control-group markup
* update typography docs for kss

* [DM] docs for all packages (#818)

* run all packages through Documentalist (easy glob change 👍)
* index.md page for each package, _nav in docs
* update nesting in datetime docs
* title in styleguide
* change default page
* fix Table links, rename page to just Table
* move color aliases table styles to live with its family

* only update scroll position when page changes (#840)

this solves the overscroll issue we had previously (cuz page doesn't change) while also ensuring that the active section is always visible when the page loads.
sidebar scrolls the active _page_ into view so you can see the entire layout, rather than just the active section!

* [DM] update documentalist for syntax highlighting (#846)

& ensure handlebars grammar

* [DM] React examples styles (#839)

* add data-page-id to Page to give all Table examples a fixed height
* BaseExample requires id prop, adds data-example-id attribute
IBaseExample interface re-used in docs example renderer.
BaseExample is the .kss-example, reducing element count by 1!
* move .docs-overlay-example-transition styles all to _examples
* sass example($name) function generates selector for react examples
* InputGroupExample uses flex box utility classes
* ContextMenuExample simpler render makes for simpler styles
* remove now unused section-name() and section-id() functions

* [DM] rename .kss-* → .docs-* (#850)

* delete unused _markup.scss file
* remove unused kss- things in html
* wholesale rename .kss-* => .docs-*

* [DM] squash some pages (#883)

* merge the slider pages by omitting JavaScript API
a daring play by ggray just lists the two components and takes advantage of documentalist's support for multiple tags per section!

* move components usage instructions to styleguide
they relate to all the packages so belong in a shared location, not inside Core Components.
now the Core package is completely empty...

* remove redundant UI icons heading in Icons as it was the only subheading.
also refine the example a bit, using some handlebars!

* [DM] core/components/button.javascript-api (#882)

* nav layout code moves to MarkdownPlugin
but must configure all plugins manually now
* support IHeadingTag with single "heading" renderer
TagRenderer receives ITag as first argument to support this polymorphism.
use type in renderer definition to avoid redeclaring each argument.
deconstruct and rename `value` as needed for minimal churn and maximal clarity.
* refactor to support `route` property
* IBlock field rename
* documentalist@0.0.5

* [DM] nav nesting (#899)

* documentalist@0.0.6: now with options
use .d.ts files for typescript info, like we used to (shaves about 2s off runtime)
* nav only expands active route, not all pages

* Documentation Overhaul (#917)

* split docs package into `docs` and `docs-site`

`docs` is the documentalist theme.
`docs-site` is the blueprint-specific content for our docs site.
write reusable tag renderers for the common tags.
this is by no means finished, just a good place to start committing

* move BaseExample into `docs` package

* move typings around

* fix docs-site webpack compile errors!

* fix sass compile errors

* require react ^15.3 so we can use PureComponent
instead of pure-render-decorator

* clean up docs common files

- move ClickToCopy to docs-site cuz it's not used in docs
- rename to propsStore.ts
- delete unused PureComponent

* move FocusStyleManager call into Styleguide componentDidMount

so consumer doesn't have to set it.
also fix typings of setHotkeysDialogProps with Partial<>.

* fix html paths

* fix broken import (forgot to save)

* rename Styleguide to Documentation

* copyright headers

* move docs-site files into same structure as docs

components / styles / tags.
tags export maps of files for reactDocs and reactExample

* Documentation navbarLeft/Right props

BlueprintDocs component wraps Documentation with added themeName state. all theme logic moves to `docs-site` custom code.

* make some Documentation props optional

* remove theme from docs

* enable strictNullChecks in docs and docs-site!!

* move docs md file, rename styleguide.md to blueprint.md

* Update to documentalist 0.0.7

* move .d.ts and README around

* move normalize.css import to docs-site.scss

until we include it in blueprint.css itself!

* fix some small build errors

* add project files

* update links to docs-site

* Add top comment block to interface table tag renderer

* export BaseExample from docs package, refactor example imports

* fix CONTRIBUTING docs path

* Null check when naving to section

* Lint

* Add docs-site artifact

* Fix gulp watch task

* minor polish

* [DM] update docs files and links (#927)

* markdownify Text and DateRangeInput docs

* fix all the links i could find

* Fix text example tag

* Fix text navbar issue

* Fix tree example styles
  • Loading branch information
themadcreator authored Apr 3, 2017
1 parent e894d61 commit f565570
Show file tree
Hide file tree
Showing 253 changed files with 5,657 additions and 6,050 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ indent_size = 2
indent_style = space

# some files use 4 spaces for indentation
[*.{js,jsx,ts,tsx,java,xml}]
[*.{js,jsx,ts,tsx,java,xml,md}]
indent_size = 4

[*.java]
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ A typical contributor workflow looks like this:
1. Create a new feature branch. We use a format like `[your-initials]/[short-name]`:
`bd/refactor-buttons`.
1. Run the development server via `gulp` (no arguments).
- Navigate to http://localhost:9000/packages/docs/dist/ when the server starts.
- Navigate to http://localhost:9000/packages/docs-site/dist/ when the server starts.
- See [Build tasks](https://github.com/palantir/blueprint/wiki/Build-tasks) on the wiki for more
details on the inner workings of the Gulp build.
- If you are contributing to the `table` or `landing` packages then run `npm start` in those
Expand Down
8 changes: 8 additions & 0 deletions Gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,18 @@ const projects = [
}, {
id: "docs",
cwd: "packages/docs/",
dependencies: ["core"],
sass: "compile",
typescript: true,
}, {
id: "docs-site",
cwd: "packages/docs-site/",
dependencies: [
// You must add your package to this dependency list if you have any
// examples in the docs.
"core",
"datetime",
"docs",
"table",
],
sass: "bundle",
Expand All @@ -87,6 +94,7 @@ const projects = [
// (they all import @blueprint/* but don't actually have themselves in their node_modules)
"@blueprintjs/core",
"@blueprintjs/datetime",
"@blueprintjs/docs",
"@blueprintjs/table",
"dom4",
"moment",
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ __Prerequisite__: Node.js v6 or v7
1. `npm install` to install build dependencies
1. `npm run bootstrap` to install and link each package using [Lerna](https://lernajs.io/)
1. `npm run gulp` to compile and start the server and watcher
1. Open your browser to [localhost:9000/packages/docs/dist/](http://localhost:9000/packages/docs/dist/)
1. Open your browser to [localhost:9000/packages/docs-site/dist/](http://localhost:9000/packages/docs-site/dist/)

## Contributing

Expand Down
2 changes: 2 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ general:
- packages/core/dist
- packages/datetime/dist
- packages/docs/dist
- packages/docs-site/dist
- packages/landing/dist
- packages/table/dist
# code coverage reports
Expand All @@ -22,6 +23,7 @@ dependencies:
- packages/core/node_modules
- packages/datetime/node_modules
- packages/docs/node_modules
- packages/docs-site/node_modules
- packages/landing/node_modules
- packages/table/node_modules
# non-zero exit codes in `dependencies` group will fail the build early
Expand Down
2 changes: 1 addition & 1 deletion gulp/aliases.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = (blueprint, gulp) => {
gulp.task("compile", ["sass", "tsc", "copy"]);

// generate docs data files
gulp.task("docs", ["docs-interfaces", "docs-kss", "docs-versions", "docs-releases"]);
gulp.task("docs", ["docs-json", "docs-versions", "docs-releases"]);

// perform a full build of the code and then finish
gulp.task("build", (done) => rs("clean", "compile", "bundle", "webpack-docs", done));
Expand Down
177 changes: 24 additions & 153 deletions gulp/docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,151 +4,47 @@
"use strict";

module.exports = (blueprint, gulp, plugins) => {
const dm = require("documentalist");
const glob = require("glob");
const path = require("path");
const text = require("./util/text");
const tsdoc = require("ts-quick-docs");
const spawn = require("child_process").spawn;
const semver = require("semver");
const cwd = blueprint.findProject("docs").cwd;
const cwd = blueprint.findProject("docs-site").cwd;

const config = {
data: path.join(cwd, "src", "generated"),
dest: path.join(cwd, "build"),
kssSources: blueprint.projectsWithBlock("sass").map((project) => path.join(project.cwd, "src")),
navPage: "_nav",
};

// paths to data files used to generate documentation app
const filenames = {
docs: "docs.json",
props: "props.json",
data: "docs.json",
releases: "releases.json",
styleguide: path.join(cwd, "src", "styleguide.md"),
versions: "versions.json",
};

const unwrapData = (section) => section.data;

function processSection(section) {
return Object.assign({}, section, {
description: text.markdown(section.description),
highlightedMarkup: text.highlight(section.markup, "text.html.handlebars"),
modifiers: section.modifiers.map(unwrapData),
parameters: section.parameters.map(unwrapData),
sections: new Map(),
});
}

// find all flags: @[flag-name] [value?]
const FLAG_REGEX = /<p>@([\w-]+)(?:\s(.+))?<\/p>/g;
function processFlags(section) {
if (typeof section.description === "string") {
section.description = section.description.replace(FLAG_REGEX, function (m, flag, value) {
switch (flag) {
case "interface":
section.interfaceName = value;
break;
case "hide-markup":
section.hideMarkup = true;
break;
case "react-docs":
section.reactDocs = value;
break;
case "react-example":
section.reactExample = value;
break;
case "angular-example":
section.angularExample = value;
break;
default:
break;
}
// remove flag from output
return "";
});
}
return section;
}

let parentsStack = [];
/**
* Convert a flat array of pages to a nested structure. Repeated references will overwrite previous instances.
* Keeps a stack of parent sections so every new section can be added to its parent.
* @param {Map<string, Object>} pages map of reference to section, to ensure uniqueness
* @param {Object} section
* @return {Map<string, object>} of top-level pages, each of which contains its sections.
*/
function nestPages(pages, section) {
// pop the stack till we find the nearest parent
let parentPage = parentsStack.pop();
while (parentPage != null && section.depth <= parentPage.depth) {
parentPage = parentsStack.pop();
}
if (parentPage == null) {
// if there's no parent then we found a new root page
parentsStack = [section];
pages.set(section.reference, section);
} else {
// otherwise add this page to its parent's sections list
parentPage.sections.set(section.reference, section);
parentsStack.push(parentPage, section);
}
return pages;
}

// JSON properties with special processing:
var EXCLUDED = ["raw", "styleguide", "weight", "autoincrement", "referenceURI", "section"];
var STRINGS = ["markup", "description"];
// JSON.stringify replacer function for Kss.Styleguide
function stringifyKss(key, value) {
if (EXCLUDED.indexOf(key) >= 0) { return undefined; }
if (STRINGS.indexOf(key) >= 0 && !value) { return undefined; }
if (key === "sections") {
// unwrap Map into array, in insertion order
return Array.from(value.values()).map(entry => entry[1]);
}
return value;
}

// run KSS against all the Sass files to extract documentation sections, then process each
// section to detect our custom @flags, then save it to a JSON file using some custom stringify
// logic to unwrap the raw KSS data.
gulp.task("docs-kss", (done) => {
var kss = require("kss");
var options = {
// disable KSS internal markdown rendering so we can do it all ourselves!
markdown: false,
mask: /\.scss$/,
};

kss.traverse(config.kssSources, options, (err, styleguide) => {
if (err) { return done(err); }

var pages = styleguide.section()
.map(unwrapData)
.map(processSection)
.map(processFlags)
.reduce(nestPages, new Map());
// convert Map to array, in insertion order
pages = Array.from(pages.values());

pages.unshift({
deprecated: false,
depth: 1,
description: text.markdown(text.fromFile(filenames.styleguide)),
experimental: false,
header: "Overview",
modifiers: [],
parameters: [],
reference: "overview",
sections: [],
});

text.fileStream(filenames.docs, JSON.stringify(pages, stringifyKss, 2))
.pipe(gulp.dest(config.data))
.on("end", done);
});
});
gulp.task("docs-json", () => (
new dm.Documentalist({
markdown: { renderer: text.renderer },
// must mark our @Decorator APIs as reserved so we can use them in code samples
reservedTags: ["ContextMenuTarget", "HotkeysTarget"],
})
.use(".md", new dm.MarkdownPlugin({ navPage: config.navPage }))
.use(/\.d\.ts$/, new dm.TypescriptPlugin({
excludeNames: [/Factory$/, /^I.+State$/],
excludePaths: ["node_modules/", "core/typings"],
includeDefinitionFiles: true,
}))
.use(".scss", new dm.KssPlugin())
.documentGlobs("packages/*/src/**/*", "packages/*/dist/index.d.ts")
.then((docs) => JSON.stringify(docs, null, 2))
.then((content) => (
text.fileStream(filenames.data, content)
.pipe(gulp.dest(config.data))
))
));

// create a JSON file containing latest released version of each project
gulp.task("docs-releases", () => {
Expand All @@ -162,31 +58,6 @@ module.exports = (blueprint, gulp, plugins) => {
.pipe(gulp.dest(config.data));
});

// must include external typings for React things like JSX.Element and React.HTMLProps
const TYPINGS_PATH = "packages/core/typings/tsd.d.ts";

gulp.task("docs-interfaces", () => {
function markdownEntry(entry) {
if (entry.documentation.length) {
entry.documentation = text.markdown(entry.documentation.trim());
}
if (entry.properties && entry.properties.length) {
entry.properties = entry.properties.map(markdownEntry);
}
return entry;
}

// load interfaces from .d.ts files
const props = tsdoc.fromFiles(glob.sync("packages/*/dist/index.d.ts").concat(TYPINGS_PATH), {}, {
excludeNames: [/Factory$/, /^I.+State$/],
excludePaths: ["node_modules/", "core/typings"],
includeDefinitionFiles: true,
}).map(markdownEntry);

return text.fileStream(filenames.props, JSON.stringify(props, null, 2))
.pipe(gulp.dest(config.data));
});

// create a JSON file containing published versions of the documentation
gulp.task("docs-versions", (done) => {
let stdout = "";
Expand Down
11 changes: 5 additions & 6 deletions gulp/util/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,9 @@ var highlighter = new Highlights();

// highlights the given text in the given language scope. returns HTML string wrapped in <pre> tag.
// must provide full TextMate language scope: "text.html.basic"
function highlight(textContent, scopeName) {
if (textContent) {
return highlighter.highlightSync({
fileContents: textContent,
scopeName: scopeName ? scopeName : DEFAULT_SCOPE,
});
function highlight(fileContents, scopeName = DEFAULT_SCOPE) {
if (fileContents) {
return highlighter.highlightSync({ fileContents, scopeName });
}
}

Expand Down Expand Up @@ -64,4 +61,6 @@ module.exports = {
// render the given text as markdown, using the custom rendering logic above.
// code blocks are highlighted using highlight() above.
markdown: (textContent) => marked(textContent, { renderer }),

renderer,
};
11 changes: 5 additions & 6 deletions gulp/watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ module.exports = (blueprint, gulp, plugins) => {
gulp.task("watch-files", ["connect"], () => {
blueprint.projectsWithBlock("sass").forEach((project) => {
const tasks = [`sass-${project.id}:only`];
if (project.id !== "docs") {
tasks.push("sass-variables", "docs-kss");
if (project.id === "core") {
tasks.push("sass-variables");
}
gulp.watch(createSrcGlob(project, "*.scss"), tasks);
});
Expand All @@ -34,11 +34,10 @@ module.exports = (blueprint, gulp, plugins) => {
gulp.watch(createSrcGlob(project, "*.ts{,x}"), [`tsc-${project.id}:only`]);
});

const docsCwd = blueprint.findProject("docs").cwd;
gulp.watch(`${docsCwd}/src/styleguide.md`, ["docs-kss"]);
gulp.watch("packages/*/!(node_modules)/**/*.md", ["docs-json"]);

// recompile docs CSS when non-docs dist/*.css files change
gulp.watch("packages/!(docs)/dist/*.css", ["sass-docs:only"]);
// recompile docs CSS when non-docs-site dist/*.css files change
gulp.watch("packages/!(docs-site)/dist/*.css", ["sass-docs-site:only"]);
});

gulp.task("watch", ["watch-files", "webpack-docs-watch"]);
Expand Down
2 changes: 1 addition & 1 deletion gulp/webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module.exports = (blueprint, gulp) => {
const webpack = require("webpack");
const webpackConfig = require("./util/webpack-config");

const docsProject = blueprint.findProject("docs");
const docsProject = blueprint.findProject("docs-site");
const configuration = webpackConfig.generateWebpackTypescriptConfig(docsProject);

gulp.task("webpack-docs", ["docs"], (callback) => {
Expand Down
30 changes: 30 additions & 0 deletions mdify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env node

const glob = require("glob");
const fs = require("fs");

// captures: [title, body, reference]
const BLOCK_REGEX = /\/\*\n(.+)\n\n((?:.|\n)+?)\nStyleguide:? (.+)\n\*\//g;

const HEADINGS = "######";

glob.sync("packages/core/src/components/*/*.scss")
.filter((filepath) => !/common\.scss$/.test(filepath))
.forEach((comp) => {
const scss = fs.readFileSync(comp, "utf-8").replace(/^ */gm, "");
const contents = [`---\nparent: ${comp.indexOf("/forms/") > 0 ? "forms" : "components"}\n---`];

/** @type {RegExpExecArray} */
let match;
// tslint:disable-next-line:no-conditional-assignment
while ((match = BLOCK_REGEX.exec(scss)) !== null) {
const [title, body, reference] = match.slice(1);
const depth = reference.split(".").length - 1;

contents.push(
`${HEADINGS.slice(0, depth)} ${title}`,
body.trim().replace(/@\w+(-\w+)/g, (tag, ext) => tag.replace(ext, ext[1].toUpperCase() + ext.slice(2)))
);
}
fs.writeFileSync(comp.replace(".scss", ".md").replace("/_", "/"), contents.join("\n\n") + "\n");
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"better-handlebars": "github:wmeldon/better-handlebars",
"chai": "3.5.0",
"del": "2.2.2",
"documentalist": "0.0.6",
"enzyme": "2.6.0",
"gulp": "3.9.1",
"gulp-concat": "2.6.0",
Expand Down Expand Up @@ -69,7 +70,6 @@
"karma-sinon": "1.0.5",
"karma-sourcemap-loader": "0.3.7",
"karma-webpack": "1.8.0",
"kss": "2.4.0",
"language-less": "github:atom/language-less",
"language-typescript": "github:giladgray/language-typescript#10.1.15",
"lerna": "2.0.0-beta.30",
Expand Down
Loading

1 comment on commit f565570

@blueprint-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation (#928)

Preview: documentation
Coverage: core | datetime

Please sign in to comment.