diff --git a/.gitignore b/.gitignore index 968793b00..192404a13 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ docs/**/*.mov docs/**/*.pxm docs/node_modules docs/dist +docs/content/assets/showcases/* # boilerplate files to work on it boilerplate/package.json diff --git a/docs/content/showcase.md b/docs/content/showcase.md index 8c09c30b8..f19003435 100644 --- a/docs/content/showcase.md +++ b/docs/content/showcase.md @@ -1,37 +1,56 @@ --- title: "See who's using Phenomic" layout: "Showcase" + +# To add you website to the showcase, just add an entry like you can see below +# Eg: +#- name: My super title +# url: http://url-of-the-website/app +# source: https://github.com/url/of-the-source-(optional-if-relevant) + list: -- name: Phenomic docs - url: https://phenomic.io/ - source: https://github.com/MoOx/phenomic/tree/master/docs - name: Putain de code ! url: http://putaindecode.io/ source: https://github.com/putaindecode/putaindecode.io + - name: PostCSS url: http://postcss.org/ source: https://github.com/postcss/postcss.org + - name: cssnano url: http://cssnano.co/ source: https://github.com/ben-eb/cssnano/tree/master/docs -- name: Stylelint - url: http://stylelint.io/ - source: https://github.com/stylelint/stylelint.io + +- name: ReactClass + url: http://reactclass.com + source: https://github.com/DavidWells/react-class/ + - name: Bluejay Wireless url: https://www.bluejaywireless.com/ -- name: Khoa Nguyen's Blog - url: https://khoanguyen.me - source: https://github.com/thangngoc89/blog + - name: SEAADE 2016 website url: http://seaade2016.vn/ source: https://github.com/thangngoc89/seaade + +- name: Stylelint + url: http://stylelint.io/ + source: https://github.com/stylelint/stylelint.io + - name: Vinspee.me url: http://vinspee.me source: https://github.com/VinSpee/vinspee.me + +- name: Khoa Nguyen's Blog + url: https://khoanguyen.me + source: https://github.com/thangngoc89/blog + - name: Learn C++ (Vietnamese) url: https://khoanguyen.me/dnh-cpp/ source: https://github.com/thangngoc89/dnh-cpp/ -- name: ReactClass - url: http://reactclass.com - source: https://github.com/DavidWells/react-class/ + +# please make your proposal on top of this line +# let this one at the end +- name: Phenomic docs + url: https://phenomic.io/ + source: https://github.com/MoOx/phenomic/tree/master/docs --- diff --git a/docs/scripts/showcase-screenshots.js b/docs/scripts/showcase-screenshots.js new file mode 100644 index 000000000..de099e6a3 --- /dev/null +++ b/docs/scripts/showcase-screenshots.js @@ -0,0 +1,90 @@ +import { resolve, join } from "path" +import fs from "fs" +import findCacheDir from "find-cache-dir" +const cacheDir = findCacheDir({ name: "phenomic", create: true }) + +import grayMatter from "gray-matter" +const showcasesFile = fs.readFileSync( + __dirname + "/../content/showcase.md", + { encoding: "utf-8" } +) +const showcases = grayMatter(showcasesFile) +const list = showcases.data.list +// .slice(0,2) // for tests + +import urlToSlug from "../web_modules/url-to-slug" + +import Nightmare from "nightmare" +const screenshotsLocation = resolve(__dirname, "../content/assets/showcases/") +const screenshots = list.reduce((screenshots, { url }) => { + const filename = urlToSlug(url) + return [ + ...screenshots, + { + url, + tmpLocation: join(cacheDir, "screenshot-" + filename + "-large.png"), + location: join(screenshotsLocation, filename + "-large.jpg"), + width: 1366, + height: 768, + }, + { + url, + tmpLocation: join(cacheDir, "screenshot-" + filename + "-small.png"), + location: join(screenshotsLocation, filename + "-small.jpg"), + width: 360, + height: 640, + }, + ] +}, []) + +const nightmare = Nightmare() +let prevUrl +screenshots.forEach(({ url, tmpLocation, width, height }) => { + try { + fs.readFileSync(tmpLocation) + } + catch (e) { + console.log("Screenshots for ", url, width, height, tmpLocation) + if (url !== prevUrl) { + nightmare + .goto(url) + .wait(8000) + } + else { + nightmare + .wait(200) // wait for some logo animations & stuff (eg putaindecode.io) + } + nightmare + .viewport(width, height) + .screenshot(tmpLocation) + } +}) + +import pngToJpg from "png-jpg" +import optimizer from "image-optim" + +nightmare + .end() + .then(() => { + console.log("✅ Showcase screenshots ready.") + console.log("✅ Showcase optimizing screenshots...") + screenshots.forEach(({ tmpLocation, location }) => { + try { + fs.readFileSync(location) + } + catch (e) { + pngToJpg( + { + input: tmpLocation, + output: location, + options: { quality: 90 }, + }, + () => { + optimizer.optimize(location) + // .then(() => console.log(location, "optimized")) + .catch((err) => console.log("Failed to optimize image", err)) + } + ) + } + }) + }) diff --git a/docs/web_modules/EditThisPage/index.js b/docs/web_modules/EditThisPage/index.js index e3e9058c6..4c0323c3b 100644 --- a/docs/web_modules/EditThisPage/index.js +++ b/docs/web_modules/EditThisPage/index.js @@ -3,22 +3,25 @@ import React, { PropTypes } from "react" import { repository } from "../../../package.json" const EditThisPage = (props) => { + const { filename, children, ...othersProps } = props return ( - { "Edit this page" } + { children ? children : "Edit this page" } ) } EditThisPage.propTypes = { filename: PropTypes.string.isRequired, + children: PropTypes.node, } export default EditThisPage diff --git a/docs/web_modules/Header/index.js b/docs/web_modules/Header/index.js index df6a7a2e7..8d826365c 100755 --- a/docs/web_modules/Header/index.js +++ b/docs/web_modules/Header/index.js @@ -103,7 +103,7 @@ class Header extends Component { activeClassName={ styles.linkActive } to="/showcase/" > - { " Showcase" } + { "Showcase" }
diff --git a/docs/web_modules/layouts/Showcase/index.css b/docs/web_modules/layouts/Showcase/index.css index 3f259a03c..f858fee71 100644 --- a/docs/web_modules/layouts/Showcase/index.css +++ b/docs/web_modules/layouts/Showcase/index.css @@ -6,6 +6,7 @@ } .item { + position: relative; flex: 1 1 20rem; box-sizing: border-box; @@ -14,6 +15,7 @@ } .itemLink { + display: block; font-size: 1.6rem; font-weight: bold; text-decoration: none; @@ -25,3 +27,30 @@ text-decoration: none; color: #006df4; } + +.itemScreenshotLarge { + max-width: 100%; + border: 1px solid color(#000 a(0.1)); + border-radius: 4px; +} + +.itemScreenshotSmall { + position: absolute; + right: 0; + bottom: 0; + max-width: 20%; + border: 1px solid color(#000 a(0.1)); + border-radius: 4px; +} + +.addYourOwn { + opacity: 0.4; + + &:hover { + opacity: 1; + } +} + +.editPage { + color: #08b09b; +} diff --git a/docs/web_modules/layouts/Showcase/index.js b/docs/web_modules/layouts/Showcase/index.js index 626e5ce66..420126cad 100644 --- a/docs/web_modules/layouts/Showcase/index.js +++ b/docs/web_modules/layouts/Showcase/index.js @@ -1,6 +1,8 @@ import React, { PropTypes } from "react" import invariant from "invariant" +import urlToSlug from "../../url-to-slug" + import Page from "../Page" import EditThisPage from "../../EditThisPage" @@ -13,9 +15,23 @@ const Showcase = (props) => { "Showcase page need a list" ) + const addYourOwn = ( +

+ + { + "Add your own website to this page!" + } + +

+ ) + return (
+ { addYourOwn }
    @@ -34,6 +50,25 @@ const Showcase = (props) => { { item.name }
    + + + + +
    { item.source && { }) }
-

- { - "To add your own you just need to " - } - -

+ { addYourOwn }
) diff --git a/docs/web_modules/url-to-slug/index.js b/docs/web_modules/url-to-slug/index.js new file mode 100644 index 000000000..6d929748a --- /dev/null +++ b/docs/web_modules/url-to-slug/index.js @@ -0,0 +1,6 @@ +export default (url) => ( + url + .replace(/https?:\/\//,"") + .replace(/\/$/,"") + .replace(/\//g,"_") +) diff --git a/package.json b/package.json index 89d97a60c..a0f63b45c 100644 --- a/package.json +++ b/package.json @@ -102,13 +102,16 @@ "expect-jsx": "^2.2.1", "flow-bin": "^0.27.0", "flow-interfaces": "^0.5.0", + "image-optim": "^3.0.0", "js-beautify": "^1.5.10", "jsdom": "^9.2.0", "lnfs": "^3.0.0", "mock-fs": "^3.9.0", + "nightmare": "^2.6.1", "npm-run-all": "^2.1.1", "npmpub": "^3.0.0", "nyc": "^6.4.3", + "png-jpg": "0.0.2", "react": "^15.0.0-rc.1", "react-addons-test-utils": "^15.0.0-rc.1", "react-dom": "^15.0.0-rc.1",