mirror of
https://github.com/composerize/composerize.git
synced 2025-12-05 18:56:02 -06:00
reorganize repo; fix issue
This commit is contained in:
27
.babelrc
Normal file
27
.babelrc
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"presets": [
|
||||
["flow"],
|
||||
[
|
||||
"env",
|
||||
{
|
||||
"targets": {
|
||||
"node": "current",
|
||||
"browsers": ["last 5 versions", "safari >= 7"]
|
||||
},
|
||||
"modules": false
|
||||
}
|
||||
]
|
||||
],
|
||||
"env": {
|
||||
"test": {
|
||||
"presets": [
|
||||
[
|
||||
"env",
|
||||
{
|
||||
"modules": "commonjs"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
root = true
|
||||
|
||||
[src/**/*.{js,jsx,css}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
charset = utf-8
|
||||
[*.{js,babelrc}]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"projects": {
|
||||
"default": "composerize-83cba"
|
||||
}
|
||||
}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,6 +6,7 @@
|
||||
|
||||
# production
|
||||
/build
|
||||
/dist
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
||||
@@ -21,11 +21,3 @@ cache:
|
||||
|
||||
script:
|
||||
- yarn build
|
||||
|
||||
deploy:
|
||||
provider: firebase
|
||||
skip_cleanup: true
|
||||
token:
|
||||
secure: ${FIREBASE_API_TOKEN}
|
||||
on:
|
||||
branch: master
|
||||
|
||||
41
__tests__/__snapshots__/index_test.js.snap
Normal file
41
__tests__/__snapshots__/index_test.js.snap
Normal file
@@ -0,0 +1,41 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`snapshots match snapshots 1`] = `
|
||||
"version: 3
|
||||
services:
|
||||
nginx:
|
||||
ports:
|
||||
- '80:80'
|
||||
volumes:
|
||||
- '/var/run/docker.sock:/tmp/docker.sock:ro'
|
||||
restart: always
|
||||
logging:
|
||||
options:
|
||||
max-size: 1g"
|
||||
`;
|
||||
|
||||
exports[`snapshots match snapshots 2`] = `
|
||||
"version: 3
|
||||
services:
|
||||
nginx:
|
||||
ports:
|
||||
- '80:80'
|
||||
volumes:
|
||||
- '/var/run/docker.sock:/tmp/docker.sock:ro'
|
||||
restart: always
|
||||
logging:
|
||||
options:
|
||||
max-size: 1g"
|
||||
`;
|
||||
|
||||
exports[`snapshots match snapshots 3`] = `
|
||||
"version: 3
|
||||
services:
|
||||
youtrack:
|
||||
volumes:
|
||||
- '/data/youtrack/data/:/opt/youtrack/data/'
|
||||
- '/data/youtrack/backup/:/opt/youtrack/backup/'
|
||||
ports:
|
||||
- '80:80'
|
||||
- '3232:22351'"
|
||||
`;
|
||||
43
__tests__/index_test.js
Normal file
43
__tests__/index_test.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import Composerize from "../src";
|
||||
import { maybeGetComposeEntry, getComposeJson } from "../src/logic";
|
||||
|
||||
describe("maybeGetComposeEntry", () => {
|
||||
it("works", () => {
|
||||
// test '--device foo'
|
||||
expect(maybeGetComposeEntry(["--device", "foo"], 0)).toMatchObject({
|
||||
path: "devices",
|
||||
value: ["foo"]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("getComposeJson", () => {
|
||||
it("works", () => {
|
||||
expect(
|
||||
getComposeJson({
|
||||
path: "devices",
|
||||
value: ["foo"]
|
||||
})
|
||||
).toMatchObject({
|
||||
devices: ["foo"]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("snapshots", () => {
|
||||
const CMDS = [
|
||||
"docker run -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro --restart always --log-opt max-size=1g nginx",
|
||||
|
||||
// test spacing
|
||||
" docker run -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro --restart always --log-opt max-size=1g nginx ",
|
||||
|
||||
// test multiple args (https://github.com/magicmark/composerize/issues/9)
|
||||
'docker run -t --name="youtrack" -v /data/youtrack/data/:/opt/youtrack/data/ -v /data/youtrack/backup/:/opt/youtrack/backup/ -p 80:80 -p 3232:22351 uniplug/youtrack'
|
||||
];
|
||||
|
||||
it("match snapshots", () => {
|
||||
CMDS.forEach(cmd => {
|
||||
expect(Composerize(cmd)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
var composerize = require('./dist/bundle');
|
||||
var composerize = require('./dist/composerize');
|
||||
var command = process.argv.slice(2).join(' ');
|
||||
console.log(composerize(command));
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"hosting": {
|
||||
"public": "build"
|
||||
}
|
||||
}
|
||||
7
jest.config.js
Normal file
7
jest.config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
bail: true,
|
||||
verbose: true,
|
||||
roots: ['<rootDir>/src/', '<rootDir>/__tests__/'],
|
||||
};
|
||||
54
package.json
54
package.json
@@ -1,24 +1,40 @@
|
||||
{
|
||||
"name": "composerize3",
|
||||
"version": "3.0.0",
|
||||
"homepage": "http://composerize.com",
|
||||
"dependencies": {
|
||||
"composerize": "1.0.0-alpha.7",
|
||||
"html5-boilerplate": "^6.0.0",
|
||||
"normalize.css": "^7.0.0",
|
||||
"react": "^15.5.4",
|
||||
"react-copy-to-clipboard": "^5.0.0",
|
||||
"react-dom": "^15.5.4",
|
||||
"react-portal-tooltip": "^1.1.5",
|
||||
"styled-components": "^2.1.2"
|
||||
"name": "composerize",
|
||||
"version": "1.0.0-alpha.7",
|
||||
"main": "dist/composerize.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"test": "node_modules/.bin/jest --no-watchman",
|
||||
"eslint": "eslint src/**/*.js --fix"
|
||||
},
|
||||
"bin": {
|
||||
"composerize": "cli.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-scripts": "1.0.11"
|
||||
"@mlarah/eslint-config": "^2.0.1",
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-eslint": "^8.0.0",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-preset-env": "^1.5.1",
|
||||
"babel-preset-flow": "^6.23.0",
|
||||
"eslint": "^4.7.2",
|
||||
"flow-bin": "^0.55.0",
|
||||
"jest": "^21.1.0",
|
||||
"rollup": "^0.50.0",
|
||||
"rollup-plugin-babel": "^3.0.2",
|
||||
"rollup-plugin-commonjs": "^8.0.2",
|
||||
"rollup-plugin-node-resolve": "^3.0.0",
|
||||
"rollup-plugin-replace": "^2.0.0",
|
||||
"rollup-plugin-uglify": "^2.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
}
|
||||
"dependencies": {
|
||||
"deepmerge": "^1.5.2",
|
||||
"spawn-args": "^0.2.0",
|
||||
"yamljs": "^0.3.0"
|
||||
},
|
||||
"files": [
|
||||
"dist/composerize.js",
|
||||
"cli.js"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
["flow"],
|
||||
["env", {
|
||||
"targets": {
|
||||
"node": "current",
|
||||
"browsers": ["last 5 versions", "safari >= 7"]
|
||||
},
|
||||
"modules": false
|
||||
}]
|
||||
],
|
||||
"plugins": [
|
||||
"external-helpers"
|
||||
],
|
||||
"env": {
|
||||
"test": {
|
||||
"presets": [
|
||||
["env", {
|
||||
"modules": "commonjs"
|
||||
}]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*.{js,babelrc}]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
1
packages/composerize/.gitignore
vendored
1
packages/composerize/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
dist
|
||||
@@ -1,24 +0,0 @@
|
||||
import { maybeGetComposeEntry, getComposeJson } from '../src/index';
|
||||
|
||||
describe('maybeGetComposeEntry', () => {
|
||||
it('works', () => {
|
||||
// test '--device foo'
|
||||
expect(maybeGetComposeEntry(['--device', 'foo'], 0)).toMatchObject({
|
||||
path: 'devices',
|
||||
value: ['foo'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getComposeJson', () => {
|
||||
it('works', () => {
|
||||
expect(
|
||||
getComposeJson({
|
||||
path: 'devices',
|
||||
value: ['foo'],
|
||||
}),
|
||||
).toMatchObject({
|
||||
devices: ['foo'],
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
"bail": true,
|
||||
"verbose": true,
|
||||
"roots": [
|
||||
"<rootDir>/src/",
|
||||
"<rootDir>/__tests__/",
|
||||
],
|
||||
}
|
||||
3491
packages/composerize/package-lock.json
generated
3491
packages/composerize/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"name": "composerize",
|
||||
"version": "1.0.0-alpha.7",
|
||||
"main": "dist/bundle.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"test": "node_modules/.bin/jest --no-watchman",
|
||||
"eslint": "eslint src/**/*.js --fix"
|
||||
},
|
||||
"bin": {
|
||||
"composerize": "cli.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mlarah/eslint-config": "^1.0.1",
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-eslint": "^7.2.3",
|
||||
"babel-jest": "^20.0.3",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"babel-preset-env": "^1.5.1",
|
||||
"babel-preset-flow": "^6.23.0",
|
||||
"eslint": "^3.19.0",
|
||||
"flow-bin": "^0.47.0",
|
||||
"jest": "^20.0.4",
|
||||
"rollup": "^0.41.6",
|
||||
"rollup-plugin-babel": "^2.7.1",
|
||||
"rollup-plugin-commonjs": "^8.0.2",
|
||||
"rollup-plugin-node-resolve": "^3.0.0",
|
||||
"rollup-plugin-replace": "^1.1.1",
|
||||
"rollup-plugin-uglify": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"spawn-args": "^0.2.0",
|
||||
"yamljs": "^0.2.10"
|
||||
},
|
||||
"files": [
|
||||
"dist/bundle.js",
|
||||
"cli.js"
|
||||
]
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// rollup.config.js
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import babel from 'rollup-plugin-babel';
|
||||
import uglify from 'rollup-plugin-uglify';
|
||||
import replace from 'rollup-plugin-replace'
|
||||
|
||||
export default {
|
||||
entry: 'src/index.js',
|
||||
format: 'cjs',
|
||||
sourceMap: 'inline',
|
||||
plugins: [
|
||||
replace({
|
||||
'process.env.NODE_ENV': JSON.stringify('production')
|
||||
}),
|
||||
resolve(),
|
||||
babel({
|
||||
exclude: 'node_modules/**', // only transpile our source code
|
||||
}),
|
||||
commonjs({
|
||||
namedExports: { 'node_modules/spawn-args/index.js': ['spawnargs'] }, // Default: undefined
|
||||
}),
|
||||
uglify()
|
||||
],
|
||||
dest: 'dist/bundle.js',
|
||||
};
|
||||
@@ -1,43 +0,0 @@
|
||||
// @flow
|
||||
import yamljs from 'yamljs';
|
||||
import spawnargs from 'spawn-args';
|
||||
|
||||
import { maybeGetComposeEntry, getComposeJson } from './logic';
|
||||
|
||||
export default (input: string): ?string => {
|
||||
const formattedInput = input.replace(/(\s)+/g, ' ').trim();
|
||||
const tokens = spawnargs(formattedInput, { removequotes: 'always' });
|
||||
|
||||
if (tokens[0] !== 'docker' || tokens[1] !== 'run') {
|
||||
throw new SyntaxError('must be a valid docker run command');
|
||||
}
|
||||
|
||||
// remove 'docker run'
|
||||
tokens.splice(0, 2);
|
||||
|
||||
// The service object that we'll update
|
||||
let service = {};
|
||||
|
||||
// Loop through the tokens and append to the service object
|
||||
tokens.forEach((token, idx) => {
|
||||
const composeEntry = maybeGetComposeEntry(tokens, idx);
|
||||
if (composeEntry) {
|
||||
// Store whatever the next entry will be
|
||||
const json = getComposeJson(composeEntry);
|
||||
service = Object.assign({}, service, json);
|
||||
}
|
||||
});
|
||||
|
||||
const image = tokens[tokens.length - 1];
|
||||
const serviceName = image.includes('/') ? image.split('/')[1] : image;
|
||||
|
||||
// Outer template
|
||||
const result = {
|
||||
version: 3,
|
||||
services: {
|
||||
[serviceName]: service,
|
||||
},
|
||||
};
|
||||
|
||||
return yamljs.stringify(result, 9, 4).trim();
|
||||
};
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 97 KiB |
@@ -1,57 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link href="https://fonts.googleapis.com/css?family=Raleway|Ubuntu+Mono" rel="stylesheet">
|
||||
<script id="twitter-wjs" src="https://platform.twitter.com/widgets.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
|
||||
<script src="https://use.fontawesome.com/4da72148cb.js"></script>
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/4da72148cb.css" media="all">
|
||||
<script type="text/javascript" charset="utf-8" async src="https://platform.twitter.com/js/button.90facfc7dd48c9c8c4f1fc94e137b515.js"></script>
|
||||
<meta name="theme-color" content="#000000">
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>Composerize</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-65092407-2', 'auto');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"short_name": "Composerize",
|
||||
"name": "Composerize",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
28
rollup.config.js
Normal file
28
rollup.config.js
Normal file
@@ -0,0 +1,28 @@
|
||||
// rollup.config.js
|
||||
import commonjs from "rollup-plugin-commonjs";
|
||||
import resolve from "rollup-plugin-node-resolve";
|
||||
import babel from "rollup-plugin-babel";
|
||||
import uglify from "rollup-plugin-uglify";
|
||||
import replace from "rollup-plugin-replace";
|
||||
|
||||
export default {
|
||||
entry: "src/index.js",
|
||||
format: "umd",
|
||||
sourceMap: "inline",
|
||||
name: "composerize",
|
||||
plugins: [
|
||||
replace({
|
||||
"process.env.NODE_ENV": JSON.stringify("production")
|
||||
}),
|
||||
resolve(),
|
||||
babel({
|
||||
plugins: ["external-helpers"],
|
||||
exclude: "node_modules/**" // only transpile our source code
|
||||
}),
|
||||
commonjs({
|
||||
namedExports: { "node_modules/spawn-args/index.js": ["spawnargs"] } // Default: undefined
|
||||
}),
|
||||
uglify()
|
||||
],
|
||||
dest: "dist/composerize.js"
|
||||
};
|
||||
11
src/App.css
11
src/App.css
@@ -1,11 +0,0 @@
|
||||
html, body, p {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:visited,
|
||||
a:active,
|
||||
a:link {
|
||||
color: #a2b8ea;
|
||||
}
|
||||
18
src/App.js
18
src/App.js
@@ -1,18 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import "normalize.css";
|
||||
import "html5-boilerplate/dist/css/main.css";
|
||||
import "./App.css";
|
||||
import Main from "./Main";
|
||||
|
||||
class App extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Main />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -1,8 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
it('renders without crashing', () => {
|
||||
const div = document.createElement('div');
|
||||
ReactDOM.render(<App />, div);
|
||||
});
|
||||
46
src/Main.jsx
46
src/Main.jsx
@@ -1,46 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import Composerize from "composerize";
|
||||
import "normalize.css";
|
||||
import "html5-boilerplate/dist/css/main.css";
|
||||
import "./App.css";
|
||||
|
||||
import Header from "./components/Header";
|
||||
import Entry from "./components/Entry";
|
||||
import Output from "./components/Output";
|
||||
import Footer from "./components/Footer";
|
||||
|
||||
const defaultCommand =
|
||||
"docker run -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro --restart always --log-opt max-size=1g nginx";
|
||||
|
||||
|
||||
export default class Main extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
input: defaultCommand,
|
||||
output: Composerize(defaultCommand),
|
||||
};
|
||||
this.onInputChange = this.onInputChange.bind(this);
|
||||
}
|
||||
|
||||
onInputChange(value) {
|
||||
this.setState({
|
||||
input: value,
|
||||
output: Composerize(value)
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Header />
|
||||
<Entry
|
||||
command={this.state.input}
|
||||
onInputChange={this.onInputChange}
|
||||
/>
|
||||
<Output output={this.state.output} />
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { css } from 'styled-components';
|
||||
|
||||
export default css`
|
||||
box-sizing: border-box;
|
||||
padding: 10px 13px;
|
||||
margin-bottom: 30px;
|
||||
width: 100%;
|
||||
border: 2px solid #cacaca;
|
||||
border-radius: 6px;
|
||||
background: #fef4f7;
|
||||
color: #28282f;
|
||||
font-size: 13px;
|
||||
font-family: 'Ubuntu Mono', monospace;
|
||||
`;
|
||||
@@ -1,10 +0,0 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
export default styled.span`
|
||||
padding: 3px 6px;
|
||||
margin: 0px 2px;
|
||||
border-radius: 7px;
|
||||
border: 1px solid #d3d4d6;
|
||||
background: #eef2fb;
|
||||
font-family: 'Ubuntu Mono', monospace;
|
||||
`;
|
||||
@@ -1,100 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import styled from "styled-components";
|
||||
import CopyToClipboard from "react-copy-to-clipboard";
|
||||
import ToolTip from "react-portal-tooltip";
|
||||
|
||||
const StyledButton = styled.a`
|
||||
float: right;
|
||||
margin: -10px -13px;
|
||||
background: #e0e0e0;
|
||||
border-radius: 0px 4px 0px 6px;
|
||||
border: 2px solid #cacaca;
|
||||
border-top: 0;
|
||||
border-right: 0;
|
||||
cursor: pointer;
|
||||
|
||||
& i {
|
||||
color: #404040;
|
||||
padding: 10px 13px;
|
||||
}
|
||||
`;
|
||||
|
||||
const toolTipBodyStyle = {
|
||||
style: {
|
||||
backgroundColor: "#222",
|
||||
color: "#eee",
|
||||
textAlign: "center",
|
||||
padding: "7px 10px",
|
||||
fontSize: "11px",
|
||||
borderRadius: "6px",
|
||||
boxShadow: "none"
|
||||
},
|
||||
arrowStyle: {
|
||||
color: "#222"
|
||||
}
|
||||
};
|
||||
|
||||
export default class Copy extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isTooltipActive: false,
|
||||
copied: false
|
||||
};
|
||||
}
|
||||
|
||||
onCopy() {
|
||||
console.log("copieddfsdf");
|
||||
this.setState({ copied: true });
|
||||
}
|
||||
|
||||
showTooltip() {
|
||||
this.setState({ isTooltipActive: true });
|
||||
}
|
||||
|
||||
hideTooltip() {
|
||||
this.setState({ isTooltipActive: false });
|
||||
}
|
||||
|
||||
render() {
|
||||
const tipText = this.state.copied ? "Copied!" : "Copy";
|
||||
|
||||
return (
|
||||
<StyledButton
|
||||
data-tip={tipText}
|
||||
data-place="top"
|
||||
data-effect="solid"
|
||||
data-for="copyToClipboard"
|
||||
>
|
||||
<CopyToClipboard
|
||||
text={this.props.output}
|
||||
onCopy={() => {
|
||||
this.onCopy();
|
||||
}}
|
||||
>
|
||||
<i
|
||||
id="copyToClipboard"
|
||||
className="fa fa-clipboard fa-2x"
|
||||
aria-hidden="true"
|
||||
onMouseEnter={() => {
|
||||
this.showTooltip();
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
this.hideTooltip();
|
||||
}}
|
||||
/>
|
||||
</CopyToClipboard>
|
||||
<ToolTip
|
||||
active={this.state.isTooltipActive}
|
||||
position="top"
|
||||
arrow="center"
|
||||
parent="#copyToClipboard"
|
||||
tooltipTimeout={0}
|
||||
style={toolTipBodyStyle}
|
||||
>
|
||||
{tipText}
|
||||
</ToolTip>
|
||||
</StyledButton>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import styled from "styled-components";
|
||||
import Section from "./Section";
|
||||
import TextInput from "./TextInput";
|
||||
import Code from "./Code";
|
||||
|
||||
const Blurb = styled.div`
|
||||
line-height: 32px;
|
||||
margin-top: -10px;
|
||||
margin-bottom: 10px;
|
||||
`;
|
||||
|
||||
export default class Entry extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Section topPadding>
|
||||
<Blurb>
|
||||
<p>
|
||||
Say goodbye to sprawling docker commands and say hello to
|
||||
{" "}
|
||||
<Code>$ docker-compose up</Code>
|
||||
{" "}
|
||||
:)
|
||||
</p>
|
||||
<p>
|
||||
Paste your
|
||||
{" "}
|
||||
<a
|
||||
href="https://docs.docker.com/engine/reference/run/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
docker run
|
||||
</a>
|
||||
{" "}
|
||||
command into the box below!
|
||||
</p>
|
||||
</Blurb>
|
||||
<TextInput
|
||||
command={this.props.command}
|
||||
onInputChange={this.props.onInputChange}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import Section from "./Section";
|
||||
|
||||
const Container = styled.ul`
|
||||
line-height: 36px;
|
||||
list-style-type: none;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-size: 12px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
const Item = styled.li`
|
||||
float: left;
|
||||
|
||||
&:not(:first-child):before {
|
||||
content: "-";
|
||||
margin-left: 9px;
|
||||
margin-right: 9px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<Section border>
|
||||
<Container>
|
||||
<Item>Composerize</Item>
|
||||
<Item>
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
href="http://twitter.com/mark_larah"
|
||||
target="_blank"
|
||||
>
|
||||
@mark_larah
|
||||
</a>
|
||||
</Item>
|
||||
<Item>
|
||||
Want to help improve composerize? Open an
|
||||
{" "}
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
href="//github.com/magicmark/composerize/issues"
|
||||
target="_blank"
|
||||
>
|
||||
issue on Github
|
||||
</a>
|
||||
!
|
||||
</Item>
|
||||
</Container>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,49 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
const Container = styled.div`
|
||||
display: block;
|
||||
position: relative;
|
||||
background: #848850;
|
||||
color: #fff;
|
||||
border-bottom: 2px solid #5f561b;
|
||||
`;
|
||||
|
||||
const Title = styled.div`
|
||||
display: inline-block;
|
||||
margin: 14px 20px;
|
||||
font-family: 'Ubuntu Mono', monospace;
|
||||
font-size: 40px;
|
||||
`;
|
||||
|
||||
const Buttons = styled.div`
|
||||
position: absolute;
|
||||
bottom: 7px;
|
||||
right: 10px;
|
||||
`;
|
||||
|
||||
const GitHubIFrame = styled.iframe`
|
||||
overflow: none
|
||||
width: 80px;
|
||||
height: 20px;
|
||||
border: 0;
|
||||
margin-right: 5px;
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<Container>
|
||||
<Title>$ composerize</Title>
|
||||
<Buttons>
|
||||
<GitHubIFrame src="https://ghbtns.com/github-btn.html?user=magicmark&repo=composerize&type=star&count=true" />
|
||||
<a
|
||||
href="https://twitter.com/share"
|
||||
className="twitter-share-button"
|
||||
data-url="http://composerize.com"
|
||||
data-text="Turn arbitrary docker run commands into docker-compose files!"
|
||||
data-dnt="true"
|
||||
>
|
||||
Tweet
|
||||
</a>
|
||||
</Buttons>
|
||||
</Container>
|
||||
);
|
||||
@@ -1,49 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import Section from "./Section";
|
||||
import Code from "./Code";
|
||||
import Results from './Results';
|
||||
|
||||
const Label = styled.div`
|
||||
display: table;
|
||||
margin-bottom: 20px;
|
||||
font-size: 11px;
|
||||
border: 1px solid #dcd4d8;
|
||||
border-top: 0px;
|
||||
background: #f7ebed;
|
||||
color: #6b2632;
|
||||
padding: 4px;
|
||||
`;
|
||||
|
||||
const Blurb = styled.div`
|
||||
line-height: 32px;
|
||||
margin-top: -10px;
|
||||
margin-bottom: 10px;
|
||||
`;
|
||||
|
||||
export default (props) => (
|
||||
<Section border>
|
||||
<Label>Output</Label>
|
||||
<Blurb>
|
||||
<p>
|
||||
Copy the following into a file called
|
||||
{" "}
|
||||
<Code>docker-compose.yml</Code>
|
||||
</p>
|
||||
<p>
|
||||
For more help, please consult the
|
||||
{" "}
|
||||
<a
|
||||
href="https://docs.docker.com/compose/compose-file/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
docker compose
|
||||
</a>
|
||||
{" "}
|
||||
documentation.
|
||||
</p>
|
||||
</Blurb>
|
||||
<Results output={props.output}/>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,46 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import styled from "styled-components";
|
||||
import CBox from "./CBox";
|
||||
import Copy from "./Copy";
|
||||
|
||||
const ResultsBox = styled.div`
|
||||
${CBox}
|
||||
`;
|
||||
|
||||
const Contents = styled.div`
|
||||
white-space: pre;
|
||||
`;
|
||||
|
||||
export default class Results extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
hoveringOverResults: false
|
||||
};
|
||||
}
|
||||
|
||||
mouseOverResults() {
|
||||
this.setState({ hoveringOverResults: true });
|
||||
}
|
||||
|
||||
mouseLeaveResults() {
|
||||
this.setState({ hoveringOverResults: false });
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ResultsBox
|
||||
onMouseEnter={() => {
|
||||
this.mouseOverResults();
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
this.mouseLeaveResults();
|
||||
}}
|
||||
>
|
||||
{this.state.hoveringOverResults &&
|
||||
<Copy output={this.props.output} />}
|
||||
<Contents>{this.props.output}</Contents>
|
||||
</ResultsBox>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// @flow
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
const Section = styled.div`
|
||||
margin: 0px 50px;
|
||||
width: 100%;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
`;
|
||||
|
||||
const Spacer = styled.div`
|
||||
display: flex;
|
||||
padding-top: ${(props) => props.topPadding ? "30" : "0"}px;
|
||||
border-top: ${(props) => props.border ? "1" : "0"}px solid #dcd4d8;
|
||||
`;
|
||||
|
||||
export default ({ children, topPadding, border }) => {
|
||||
return (
|
||||
<Spacer
|
||||
topPadding={topPadding}
|
||||
border={border}
|
||||
>
|
||||
<Section>{children}</Section>
|
||||
</Spacer>
|
||||
);
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
import React, { Component } from "react";
|
||||
import styled from "styled-components";
|
||||
import CBox from "./CBox";
|
||||
|
||||
const StyledInput = styled.input`
|
||||
${CBox}
|
||||
`;
|
||||
|
||||
export default class TextInput extends Component {
|
||||
handleChange(e) {
|
||||
this.props.onInputChange(e.target.value);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { command } = this.props;
|
||||
|
||||
return (
|
||||
<StyledInput
|
||||
value={command}
|
||||
onChange={e => {
|
||||
this.handleChange(e);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
50
src/index.js
50
src/index.js
@@ -1,8 +1,44 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import registerServiceWorker from './registerServiceWorker';
|
||||
import './index.css';
|
||||
// @flow
|
||||
import yamljs from "yamljs";
|
||||
import spawnargs from "spawn-args";
|
||||
import deepmerge from "deepmerge";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
registerServiceWorker();
|
||||
import { maybeGetComposeEntry, getComposeJson } from "./logic";
|
||||
|
||||
export default (input: string): ?string => {
|
||||
const formattedInput = input.replace(/(\s)+/g, " ").trim();
|
||||
const tokens = spawnargs(formattedInput, { removequotes: "always" });
|
||||
|
||||
if (tokens[0] !== "docker" || tokens[1] !== "run") {
|
||||
throw new SyntaxError("must be a valid docker run command");
|
||||
}
|
||||
|
||||
// remove 'docker run'
|
||||
tokens.splice(0, 2);
|
||||
|
||||
// The service object that we'll update
|
||||
let service = {};
|
||||
|
||||
// Loop through the tokens and append to the service object
|
||||
tokens.forEach((token, idx) => {
|
||||
const composeEntry = maybeGetComposeEntry(tokens, idx);
|
||||
if (composeEntry) {
|
||||
// Store whatever the next entry will be
|
||||
const json = getComposeJson(composeEntry);
|
||||
service = deepmerge(service, json);
|
||||
}
|
||||
});
|
||||
|
||||
const image = tokens[tokens.length - 1];
|
||||
const serviceName = image.includes("/") ? image.split("/")[1] : image;
|
||||
|
||||
// Outer template
|
||||
const result = {
|
||||
version: 3,
|
||||
services: {
|
||||
[serviceName]: service
|
||||
}
|
||||
};
|
||||
|
||||
return yamljs.stringify(result, 9, 4).trim();
|
||||
};
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
// In production, we register a service worker to serve assets from local cache.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on the "N+1" visit to a page, since previously
|
||||
// cached resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
|
||||
// This link also includes instructions on opting out of this behavior.
|
||||
|
||||
export default function register() {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the old content will have been purged and
|
||||
// the fresh content will have been added to the cache.
|
||||
// It's the perfect time to display a "New content is
|
||||
// available; please refresh." message in your web app.
|
||||
console.log('New content is available; please refresh.');
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister();
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user