├── public └── index.html ├── .dockerignore ├── index.php ├── resources ├── samples │ ├── plaintext │ ├── handlebars │ ├── http │ ├── git │ ├── xml │ ├── ini │ ├── py │ ├── html │ ├── applescript │ ├── haml │ ├── powershell │ ├── jade │ ├── markdown │ ├── twig │ ├── csharp │ ├── js │ ├── latex │ ├── actionscript │ ├── smarty │ ├── swift │ ├── bash │ ├── css │ ├── go │ ├── sql │ ├── scheme │ ├── gherkin │ ├── ruby │ ├── perl │ ├── dart │ ├── c │ ├── less │ ├── objectivec │ ├── coffeescript │ ├── java │ ├── scala │ ├── rust │ ├── nasm │ ├── matlab │ ├── php │ ├── abap │ ├── erlang │ ├── groovy │ └── sass ├── config │ └── meta.php └── views │ ├── globals.php │ ├── repo.php │ └── blob.php ├── client ├── me │ ├── index.ts │ ├── types.ts │ └── actions.ts ├── prism │ ├── themes │ │ ├── coy.lazy.css │ │ ├── default.lazy.css │ │ ├── cb.lazy.css │ │ ├── dark.lazy.css │ │ ├── funky.lazy.css │ │ ├── vs.lazy.css │ │ ├── okaidia.lazy.css │ │ ├── tomorrow.lazy.css │ │ ├── twilight.lazy.css │ │ ├── darcula.lazy.css │ │ ├── ghcolors.lazy.css │ │ ├── pojoaque.lazy.css │ │ ├── xonokai.lazy.css │ │ ├── a11y-dark.lazy.css │ │ ├── atom-dark.lazy.css │ │ ├── duotone-sea.lazy.css │ │ ├── hopscotch.lazy.css │ │ ├── duotone-dark.lazy.css │ │ ├── duotone-earth.lazy.css │ │ ├── duotone-light.lazy.css │ │ ├── duotone-space.lazy.css │ │ ├── duotone-forest.lazy.css │ │ └── base16-ateliersulphurpool-light.lazy.css │ ├── plugins │ │ ├── toolbar.lazy.css │ │ ├── line-numbers.lazy.css │ │ ├── line-highlight.lazy.css │ │ ├── show-invisibles.lazy.css │ │ ├── toolbar.ts │ │ ├── line-numbers.ts │ │ ├── line-highlight.ts │ │ ├── show-invisibles.ts │ │ ├── copy-to-clipboard.ts │ │ ├── edit.ts │ │ └── filename.ts │ └── __tests__ │ │ └── prism.spec.ts ├── snippet │ ├── index.ts │ ├── actions.ts │ └── types.ts ├── settings │ ├── index.ts │ ├── types.ts │ └── actions.ts ├── block │ ├── EditEmbed │ │ └── EditEmbed.module.scss │ ├── index.ts │ ├── __stories__ │ │ └── Shortcode.stories.tsx │ ├── SetEmbed │ │ ├── CreateOrChoose.module.scss │ │ ├── __stories__ │ │ │ └── CreateOrChoose.stories.tsx │ │ ├── Creating │ │ │ └── index.tsx │ │ ├── __tests__ │ │ │ └── CreateOrChoose.spec.tsx │ │ └── CreateOrChoose.tsx │ ├── Shortcode.tsx │ └── __tests__ │ │ ├── state.spec.ts │ │ └── block.spec.tsx ├── helpers │ ├── index.ts │ ├── link.ts │ ├── i18n.ts │ └── __tests__ │ │ └── i18n.spec.ts ├── components │ ├── SettingsPage │ │ ├── Header │ │ │ ├── index.scss │ │ │ ├── __stories__ │ │ │ │ └── Header.stories.tsx │ │ │ └── index.tsx │ │ ├── Jobs │ │ │ ├── types.ts │ │ │ ├── __stories__ │ │ │ │ └── Jobs.stories.tsx │ │ │ ├── __tests__ │ │ │ │ └── Jobs.spec.tsx │ │ │ ├── Row.tsx │ │ │ └── index.tsx │ │ ├── Accounts │ │ │ ├── __stories__ │ │ │ │ └── Accounts.stories.tsx │ │ │ └── __tests__ │ │ │ │ └── Accounts.spec.tsx │ │ ├── Messages │ │ │ └── __stories__ │ │ │ │ └── Messages.stories.tsx │ │ ├── Runs │ │ │ └── __stories__ │ │ │ │ └── Runs.stories.tsx │ │ └── Highlighting │ │ │ └── __stories__ │ │ │ └── Highlighting.stories.tsx │ ├── Loader │ │ ├── __stories__ │ │ │ └── Loader.stories.tsx │ │ ├── index.tsx │ │ └── Loader.scss │ ├── Blob │ │ ├── types.ts │ │ ├── index.tsx │ │ ├── __stories__ │ │ │ └── Blob.stories.tsx │ │ └── Code.tsx │ ├── index.ts │ ├── Editor │ │ ├── Pre.tsx │ │ ├── types.ts │ │ ├── __stories__ │ │ │ └── Editor.stories.tsx │ │ └── util.ts │ ├── SearchPopup │ │ ├── index.scss │ │ └── __stories__ │ │ │ └── SearchPopup.stories.tsx │ ├── Repo │ │ └── index.tsx │ ├── EditPage │ │ ├── __stories__ │ │ │ ├── Description.stories.tsx │ │ │ └── EditPage.stories.tsx │ │ ├── index.scss │ │ └── Description.scss │ └── Commits │ │ └── index.scss ├── editor │ ├── keyCodes.ts │ ├── index.tsx │ ├── types.tsx │ ├── actions.ts │ └── __stories__ │ │ └── Editor.stories.tsx ├── selectors │ ├── index.ts │ ├── jobs.ts │ ├── api.ts │ ├── dom.ts │ └── location.ts ├── api │ └── Toggle.ts ├── pages │ ├── block │ │ └── index.ts │ ├── edit │ │ ├── router.ts │ │ └── View.tsx │ └── settings │ │ ├── router.ts │ │ └── state.ts ├── search │ ├── View.module.scss │ ├── index.ts │ ├── context.tsx │ ├── selectors.tsx │ ├── ResultsPlaceholder.tsx │ ├── SearchResult.module.scss │ ├── actions.ts │ └── __tests__ │ │ └── SearchResult.spec.tsx ├── actions │ ├── accounts.ts │ ├── init.ts │ ├── index.ts │ ├── router.ts │ ├── author.ts │ ├── highlighting.ts │ ├── commits.ts │ └── ajax.ts ├── globals │ ├── actions.ts │ ├── index.ts │ ├── context.tsx │ ├── state.ts │ └── __tests__ │ │ └── state.spec.ts ├── sheet-router.d.ts ├── wp │ ├── Button.tsx │ ├── index.ts │ ├── TextControl.tsx │ ├── SelectControl.tsx │ ├── notices.module.scss │ ├── CheckboxControl.tsx │ ├── actions.ts │ └── notices.tsx ├── reducers │ ├── index.ts │ ├── gist.ts │ ├── repo.ts │ ├── route.ts │ ├── runs.ts │ ├── messages.ts │ ├── authors.ts │ ├── ajax.ts │ ├── prism.ts │ ├── commits.ts │ └── search.ts ├── css.d.ts ├── RootAction.ts ├── deltas │ ├── __tests__ │ │ ├── siteDelta.spec.ts │ │ ├── userDelta.spec.ts │ │ ├── searchDelta.spec.ts │ │ ├── webpackDelta.spec.ts │ │ ├── repoDelta.spec.ts │ │ └── routerDelta.spec.ts │ ├── webpackDelta.ts │ └── index.ts ├── __tests__ │ └── storyshots.spec.ts └── setupTests.ts ├── commands ├── index.tsx └── fs.ts ├── icon-128x128.png ├── screenshot-1.png ├── screenshot-2.png ├── screenshot-3.png ├── screenshot-4.png ├── screenshot-5.png ├── screenshot-6.png ├── screenshot-7.png ├── __mocks__ └── lazy.js ├── .env.example ├── jest-puppeteer.config.js ├── .wp-env.json ├── e2e ├── reset-site.sh ├── __image_snapshots__ │ ├── content-spec-ts-content-should-display-c-c-1-snap.png │ ├── content-spec-ts-content-should-display-go-go-1-snap.png │ ├── content-spec-ts-content-should-display-r-r-1-snap.png │ ├── content-spec-ts-content-should-display-css-css-1-snap.png │ ├── content-spec-ts-content-should-display-git-git-1-snap.png │ ├── content-spec-ts-content-should-display-ini-ini-1-snap.png │ ├── content-spec-ts-content-should-display-php-php-1-snap.png │ ├── content-spec-ts-content-should-display-sql-sql-1-snap.png │ ├── content-spec-ts-content-should-display-xml-xml-1-snap.png │ ├── content-spec-ts-content-should-display-abap-abap-1-snap.png │ ├── content-spec-ts-content-should-display-bash-bash-1-snap.png │ ├── content-spec-ts-content-should-display-c-csharp-1-snap.png │ ├── content-spec-ts-content-should-display-dart-dart-1-snap.png │ ├── content-spec-ts-content-should-display-haml-haml-1-snap.png │ ├── content-spec-ts-content-should-display-html-html-1-snap.png │ ├── content-spec-ts-content-should-display-http-http-1-snap.png │ ├── content-spec-ts-content-should-display-java-java-1-snap.png │ ├── content-spec-ts-content-should-display-less-less-1-snap.png │ ├── content-spec-ts-content-should-display-nasm-nasm-1-snap.png │ ├── content-spec-ts-content-should-display-perl-perl-1-snap.png │ ├── content-spec-ts-content-should-display-python-py-1-snap.png │ ├── content-spec-ts-content-should-display-ruby-ruby-1-snap.png │ ├── content-spec-ts-content-should-display-rust-rust-1-snap.png │ ├── content-spec-ts-content-should-display-twig-twig-1-snap.png │ ├── content-spec-ts-content-should-display-scala-scala-1-snap.png │ ├── content-spec-ts-content-should-display-swift-swift-1-snap.png │ ├── content-spec-ts-content-should-display-eiffel-eiffel-1-snap.png │ ├── content-spec-ts-content-should-display-erlang-erlang-1-snap.png │ ├── content-spec-ts-content-should-display-gherkin-gherkin-1-snap.png │ ├── content-spec-ts-content-should-display-groovy-groovy-1-snap.png │ ├── content-spec-ts-content-should-display-java-script-js-1-snap.png │ ├── content-spec-ts-content-should-display-la-te-x-latex-1-snap.png │ ├── content-spec-ts-content-should-display-matlab-matlab-1-snap.png │ ├── content-spec-ts-content-should-display-sass-sass-sass-1-snap.png │ ├── content-spec-ts-content-should-display-scheme-scheme-1-snap.png │ ├── content-spec-ts-content-should-display-smarty-smarty-1-snap.png │ ├── settings-spec-ts-settings-should-change-save-the-theme-1-snap.png │ ├── content-spec-ts-content-should-display-markdown-markdown-1-snap.png │ ├── content-spec-ts-content-should-display-plain-text-plaintext-1-snap.png │ ├── content-spec-ts-content-should-display-handlebars-handlebars-1-snap.png │ ├── content-spec-ts-content-should-display-objective-c-objectivec-1-snap.png │ ├── content-spec-ts-content-should-display-power-shell-powershell-1-snap.png │ ├── content-spec-ts-content-should-display-apple-script-applescript-1-snap.png │ ├── content-spec-ts-content-should-display-action-script-actionscript-1-snap.png │ ├── content-spec-ts-content-should-display-coffee-script-coffeescript-1-snap.png │ ├── settings-spec-ts-settings-should-change-save-the-line-numbers-configuration-1-snap.png │ ├── settings-spec-ts-settings-should-change-save-the-show-invisibles-configuration-1-snap.png │ └── settings-spec-ts-settings-should-show-the-settings-page-with-default-settings-1-snap.png ├── setupTests.ts └── content.spec.ts ├── app ├── Contract │ ├── Repository.php │ ├── Translations.php │ ├── Templating.php │ └── Job.php ├── Jobs │ ├── Level.php │ ├── Status.php │ └── Manager.php ├── Http │ ├── Filter │ │ ├── Search.php │ │ ├── RepoUpdate.php │ │ ├── RepoResource.php │ │ ├── BlobUpdate.php │ │ ├── BaseFilter.php │ │ └── RepoCollection.php │ ├── SiteController.php │ ├── StateController.php │ ├── CommitController.php │ └── UserController.php ├── Params │ ├── demo-code │ ├── Repository.php │ ├── Gist.php │ └── Prism.php ├── helpers.php ├── Model │ └── Message.php └── Console │ └── Binding.php ├── .storybook ├── preview.js └── main.js ├── uninstall.php ├── .svnignore ├── .github └── workflows │ └── node.js.yml ├── test ├── Integration │ ├── Console │ │ ├── Repo │ │ │ ├── TestCase.php │ │ │ └── GetTest.php │ │ ├── Blob │ │ │ ├── TestCase.php │ │ │ └── UpdateTest.php │ │ ├── Site │ │ │ └── TestCase.php │ │ ├── User │ │ │ ├── TestCase.php │ │ │ ├── GetTest.php │ │ │ └── PatchTest.php │ │ └── TestCase.php │ ├── Http │ │ └── Site │ │ │ └── ResourceTest.php │ └── TestCase.php ├── Unit │ ├── Client │ │ └── GistTest.php │ ├── Console │ │ └── Binding.php │ ├── LifecycleTest.php │ ├── Register │ │ └── Router.php │ ├── Model │ │ └── LanguageTest.php │ ├── Params │ │ └── EditorTest.php │ └── View │ │ └── TranslationsTest.php └── Factory.php ├── bin ├── docker-compose.override.yml.template └── reset-docker-db.sh ├── tsconfig.json ├── .editorconfig ├── .gitignore ├── phpunit.xml.dist └── wp-gistpen.php /public/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | Hours 2 | 3 | 8 | -------------------------------------------------------------------------------- /client/prism/plugins/line-highlight.ts: -------------------------------------------------------------------------------- 1 | import 'prismjs/plugins/line-highlight/prism-line-highlight'; 2 | 3 | export { default as plugin } from './line-highlight.lazy.css'; 4 | -------------------------------------------------------------------------------- /client/components/SettingsPage/Jobs/types.ts: -------------------------------------------------------------------------------- 1 | export type Job = { 2 | name: string; 3 | description: string; 4 | slug: string; 5 | status: 'idle' | 'processing'; 6 | }; 7 | -------------------------------------------------------------------------------- /client/prism/plugins/show-invisibles.ts: -------------------------------------------------------------------------------- 1 | import 'prismjs/plugins/show-invisibles/prism-show-invisibles'; 2 | 3 | export { default as plugin } from './show-invisibles.lazy.css'; 4 | -------------------------------------------------------------------------------- /client/api/Toggle.ts: -------------------------------------------------------------------------------- 1 | import * as t from 'io-ts'; 2 | 3 | export const Toggle = t.union([t.literal('on'), t.literal('off')]); 4 | 5 | export type Toggle = t.TypeOf; 6 | -------------------------------------------------------------------------------- /client/pages/block/index.ts: -------------------------------------------------------------------------------- 1 | import { registerBlockType } from '@wordpress/blocks'; 2 | import { config } from '../../block'; 3 | 4 | registerBlockType('intraxia/gistpen', config); 5 | -------------------------------------------------------------------------------- /client/search/View.module.scss: -------------------------------------------------------------------------------- 1 | .search { 2 | display: flex; 3 | flex-direction: row; 4 | align-items: center; 5 | } 6 | 7 | .grow { 8 | flex-grow: 1; 9 | } 10 | -------------------------------------------------------------------------------- /e2e/reset-site.sh: -------------------------------------------------------------------------------- 1 | echo '{"prism":{"theme":"default","line-numbers":false,"show-invisibles":false},"gist":{"token":""}}' | npm run env run tests-cli "gistpen site patch --format=json" 2 | -------------------------------------------------------------------------------- /client/prism/plugins/copy-to-clipboard.ts: -------------------------------------------------------------------------------- 1 | import 'prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard'; 2 | 3 | export const plugin = { 4 | use() {}, 5 | 6 | unuse() {}, 7 | }; 8 | -------------------------------------------------------------------------------- /client/selectors/jobs.ts: -------------------------------------------------------------------------------- 1 | import { JobResult, JobSuccess } from '../reducers'; 2 | 3 | export const jobIsSuccess = (job: JobResult): job is JobSuccess => 4 | job.result === 'success'; 5 | -------------------------------------------------------------------------------- /resources/samples/http: -------------------------------------------------------------------------------- 1 | POST /task?id=1 HTTP/1.1 2 | Host: example.org 3 | Content-Type: application/json; charset=utf-8 4 | Content-Length: 19 5 | 6 | {"status": "ok", "extended": true} 7 | -------------------------------------------------------------------------------- /client/editor/index.tsx: -------------------------------------------------------------------------------- 1 | export { editorStateChange } from './actions'; 2 | export { default as Editor } from './Editor'; 3 | export { ToolbarItem, ToolbarInput, ToolbarSelect } from './toolbar'; 4 | -------------------------------------------------------------------------------- /client/helpers/link.ts: -------------------------------------------------------------------------------- 1 | import { getUrl } from '../selectors'; 2 | 3 | export default function link(param: string, name: string): string { 4 | return getUrl(param, { name, parts: {} }); 5 | } 6 | -------------------------------------------------------------------------------- /app/Contract/Repository.php: -------------------------------------------------------------------------------- 1 | (value: string) => resolve({ value }), 6 | ); 7 | -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-abap-abap-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-abap-abap-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-bash-bash-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-bash-bash-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-c-csharp-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-c-csharp-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-dart-dart-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-dart-dart-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-haml-haml-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-haml-haml-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-html-html-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-html-html-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-http-http-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-http-http-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-java-java-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-java-java-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-less-less-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-less-less-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-nasm-nasm-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-nasm-nasm-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-perl-perl-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-perl-perl-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-python-py-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-python-py-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-ruby-ruby-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-ruby-ruby-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-rust-rust-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-rust-rust-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-twig-twig-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-twig-twig-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-scala-scala-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-scala-scala-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-swift-swift-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-swift-swift-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-eiffel-eiffel-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-eiffel-eiffel-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-erlang-erlang-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-erlang-erlang-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-gherkin-gherkin-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-gherkin-gherkin-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-groovy-groovy-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-groovy-groovy-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-java-script-js-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-java-script-js-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-la-te-x-latex-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-la-te-x-latex-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-matlab-matlab-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-matlab-matlab-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-sass-sass-sass-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-sass-sass-sass-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-scheme-scheme-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-scheme-scheme-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-smarty-smarty-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-smarty-smarty-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/settings-spec-ts-settings-should-change-save-the-theme-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/settings-spec-ts-settings-should-change-save-the-theme-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-markdown-markdown-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-markdown-markdown-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-plain-text-plaintext-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-plain-text-plaintext-1-snap.png -------------------------------------------------------------------------------- /resources/samples/git: -------------------------------------------------------------------------------- 1 | # On branch prism-examples 2 | # Changes to be committed: 3 | # (use "git reset HEAD <file>..." to unstage) 4 | # 5 | # new file: examples/prism-git.html 6 | 7 | - Some deleted line 8 | + Some added line 9 | -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-handlebars-handlebars-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-handlebars-handlebars-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-objective-c-objectivec-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-objective-c-objectivec-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-power-shell-powershell-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-power-shell-powershell-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-apple-script-applescript-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-apple-script-applescript-1-snap.png -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | import { addDecorator } from '@storybook/react'; 2 | import { withJunction } from 'brookjs-desalinate'; 3 | import { setAutoloaderPath } from '../client/prism'; 4 | 5 | setAutoloaderPath('/'); 6 | 7 | addDecorator(withJunction); 8 | -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-action-script-actionscript-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-action-script-actionscript-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/content-spec-ts-content-should-display-coffee-script-coffeescript-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/content-spec-ts-content-should-display-coffee-script-coffeescript-1-snap.png -------------------------------------------------------------------------------- /client/block/__stories__/Shortcode.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | import { Shortcode } from '../Shortcode'; 4 | 5 | storiesOf('Shortcode', module).add('default', () => ); 6 | -------------------------------------------------------------------------------- /client/actions/init.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'typesafe-actions'; 2 | import { GlobalsState } from '../globals'; 3 | 4 | export const init = createAction( 5 | 'INIT', 6 | resolve => (initial: { globals: Partial }) => resolve(initial), 7 | ); 8 | -------------------------------------------------------------------------------- /client/components/Loader/__stories__/Loader.stories.tsx: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/react'; 2 | import React from 'react'; 3 | import Loader from '../'; 4 | 5 | storiesOf('Loader', module).add('default', () => ( 6 | 7 | )); 8 | -------------------------------------------------------------------------------- /client/components/SettingsPage/Accounts/__stories__/Accounts.stories.tsx: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/react'; 2 | import React from 'react'; 3 | import Accounts from '../'; 4 | 5 | storiesOf('Accounts', module).add('default', () => ); 6 | -------------------------------------------------------------------------------- /client/globals/actions.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'typesafe-actions'; 2 | import { GlobalsState } from './state'; 3 | 4 | export const globalsChanged = createAction( 5 | 'GLOBALS_CHANGED', 6 | resolve => (globals: Partial) => resolve(globals), 7 | ); 8 | -------------------------------------------------------------------------------- /e2e/__image_snapshots__/settings-spec-ts-settings-should-change-save-the-line-numbers-configuration-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/settings-spec-ts-settings-should-change-save-the-line-numbers-configuration-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/settings-spec-ts-settings-should-change-save-the-show-invisibles-configuration-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/settings-spec-ts-settings-should-change-save-the-show-invisibles-configuration-1-snap.png -------------------------------------------------------------------------------- /e2e/__image_snapshots__/settings-spec-ts-settings-should-show-the-settings-page-with-default-settings-1-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intraxia/wp-gistpen/HEAD/e2e/__image_snapshots__/settings-spec-ts-settings-should-show-the-settings-page-with-default-settings-1-snap.png -------------------------------------------------------------------------------- /resources/samples/xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ok 4 | 5 | magical. 7 | ]]> 8 | 9 | 10 | -------------------------------------------------------------------------------- /client/pages/edit/router.ts: -------------------------------------------------------------------------------- 1 | import sheetRouter from 'sheet-router'; 2 | import { routeChange } from '../../actions'; 3 | 4 | export default sheetRouter({ default: '/editor' }, [ 5 | ['/editor', () => routeChange('editor')], 6 | ['/commits', () => routeChange('commits')], 7 | ]); 8 | -------------------------------------------------------------------------------- /resources/config/meta.php: -------------------------------------------------------------------------------- 1 | '2.0.0-beta.0', 13 | 'prefix' => 'wpgp', 14 | ]; 15 | -------------------------------------------------------------------------------- /client/components/Blob/types.ts: -------------------------------------------------------------------------------- 1 | export type Props = { 2 | blob: { 3 | code: string; 4 | filename: string; 5 | language: string; 6 | }; 7 | prism: { 8 | theme: string; 9 | 'line-numbers': boolean; 10 | 'show-invisibles': boolean; 11 | }; 12 | }; 13 | -------------------------------------------------------------------------------- /commands/fs.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import Kefir from 'kefir'; 3 | 4 | export default { 5 | access(path: string) { 6 | return Kefir.fromNodeCallback(callback => 7 | fs.access(path, err => callback(err)) 8 | ); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /client/components/Loader/index.tsx: -------------------------------------------------------------------------------- 1 | import './Loader.scss'; 2 | import React from 'react'; 3 | 4 | type Props = { 5 | text: string; 6 | }; 7 | 8 | const Loader: React.FC = ({ text }) => ( 9 |
{text}
10 | ); 11 | 12 | export default Loader; 13 | -------------------------------------------------------------------------------- /client/components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Blob } from './Blob'; 2 | export { default as Commits } from './Commits'; 3 | export { default as EditPage } from './EditPage'; 4 | export { default as SearchPopup } from './SearchPopup'; 5 | export { default as SettingsPage } from './SettingsPage'; 6 | -------------------------------------------------------------------------------- /resources/views/globals.php: -------------------------------------------------------------------------------- 1 | window.__GISTPEN_GLOBALS__ = ' . wp_json_encode( $data['globals'] ) . ';'; 10 | -------------------------------------------------------------------------------- /client/actions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './accounts'; 2 | export * from './ajax'; 3 | export * from './author'; 4 | export * from './commits'; 5 | export * from './editor'; 6 | export * from './highlighting'; 7 | export * from './init'; 8 | export * from './jobs'; 9 | export * from './router'; 10 | -------------------------------------------------------------------------------- /client/search/index.ts: -------------------------------------------------------------------------------- 1 | import * as actions from './actions'; 2 | 3 | export { default as Choosing } from './Choosing'; 4 | export { 5 | SearchApiResponse, 6 | SearchBlobsApiResponse, 7 | SearchBlob, 8 | SearchRepo, 9 | SearchReposApiResponse, 10 | } from './delta'; 11 | export { actions }; 12 | -------------------------------------------------------------------------------- /app/Jobs/Level.php: -------------------------------------------------------------------------------- 1 | ) => e$.map(click), 8 | }; 9 | 10 | export default toJunction(events)(Button); 11 | -------------------------------------------------------------------------------- /resources/samples/ini: -------------------------------------------------------------------------------- 1 | ;Settings relating to the location and loading of the database 2 | [Database] 3 | ProfileDir=. 4 | ShowProfileMgr=smart 5 | Profile1_Name[] = "\|/_-=MegaDestoyer=-_\|/" 6 | DefaultProfile=True 7 | AutoCreate = no 8 | 9 | [AutoExec] 10 | use-prompt="prompt" 11 | Glob=autoexec_*.ini 12 | AskAboutIgnoredPlugins=0 13 | -------------------------------------------------------------------------------- /resources/samples/py: -------------------------------------------------------------------------------- 1 | @requires_authorization 2 | def somefunc(param1='', param2=0): 3 | r'''A docstring''' 4 | if param1 > param2: # interesting 5 | print 'Gre\'ater' 6 | return (param2 - param1 + 1 + 0b10l) or None 7 | 8 | class SomeClass: 9 | pass 10 | 11 | >>> message = '''interpreter 12 | ... prompt''' 13 | -------------------------------------------------------------------------------- /client/actions/router.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'typesafe-actions'; 2 | 3 | type RouteParts = { 4 | [key: string]: string; 5 | }; 6 | 7 | type Routes = string; 8 | 9 | export const routeChange = createAction( 10 | 'ROUTE_CHANGE', 11 | resolve => (name: Routes, parts: RouteParts = {}) => resolve({ name, parts }), 12 | ); 13 | -------------------------------------------------------------------------------- /resources/samples/html: -------------------------------------------------------------------------------- 1 | 2 | Title 3 | 4 | 5 | 6 | 9 | 10 | 11 |

Title

12 | 13 | 14 | -------------------------------------------------------------------------------- /client/block/SetEmbed/CreateOrChoose.module.scss: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 100%; 3 | } 4 | 5 | .group { 6 | display: flex; 7 | flex-direction: row; 8 | justify-content: space-around; 9 | align-items: center; 10 | } 11 | 12 | .or { 13 | font-weight: bold; 14 | } 15 | 16 | .header { 17 | text-align: center; 18 | } 19 | -------------------------------------------------------------------------------- /client/me/types.ts: -------------------------------------------------------------------------------- 1 | import * as t from 'io-ts'; 2 | import { Toggle } from '../api'; 3 | 4 | export const ApiMe = t.type({ 5 | editor: t.type({ 6 | indent_width: t.string, 7 | invisibles_enabled: Toggle, 8 | tabs_enabled: Toggle, 9 | theme: t.string, 10 | }), 11 | }); 12 | 13 | export type ApiMe = t.TypeOf; 14 | -------------------------------------------------------------------------------- /uninstall.php: -------------------------------------------------------------------------------- 1 | (defaultPrism); 5 | 6 | export const usePrismConfig = () => useContext(PrismConfigContext); 7 | 8 | export const PrismConfigProvider = PrismConfigContext.Provider; 9 | -------------------------------------------------------------------------------- /client/wp/TextControl.tsx: -------------------------------------------------------------------------------- 1 | import { toJunction } from 'brookjs'; 2 | import { TextControl } from '@wordpress/components'; 3 | import { Stream } from 'kefir'; 4 | import { change } from './actions'; 5 | 6 | const events = { 7 | onChange: (e$: Stream) => e$.map(change), 8 | }; 9 | 10 | export default toJunction(events)(TextControl); 11 | -------------------------------------------------------------------------------- /.svnignore: -------------------------------------------------------------------------------- 1 | __mocks__ 2 | .storybook 3 | bin 4 | client 5 | commands 6 | e2e 7 | node_modules 8 | test 9 | .beaverrc.js 10 | .dockerignore 11 | .editorconfig 12 | .env.example 13 | .gitignore 14 | .svnignore 15 | .travis.yml 16 | jest-puppeteer.config.js 17 | setupTests.js 18 | stylelint.config.js 19 | *.json 20 | *.lock 21 | *.md 22 | *.xml.dist 23 | *.yml 24 | -------------------------------------------------------------------------------- /client/wp/SelectControl.tsx: -------------------------------------------------------------------------------- 1 | import { toJunction } from 'brookjs'; 2 | import { SelectControl } from '@wordpress/components'; 3 | import { Stream } from 'kefir'; 4 | import { change } from './actions'; 5 | 6 | const events = { 7 | onChange: (e$: Stream) => e$.map(change), 8 | }; 9 | 10 | export default toJunction(events)(SelectControl); 11 | -------------------------------------------------------------------------------- /resources/samples/applescript: -------------------------------------------------------------------------------- 1 | repeat 5 times 2 | if foo is greater than bar then 3 | display dialog "Hello there" 4 | else 5 | beep 6 | end if 7 | end repeat 8 | 9 | (* comment (*nested comment*) *) 10 | on do_something(s, y) 11 | return {s + pi, y mod 4} 12 | end do_something 13 | 14 | do shell script "/bin/echo 'hello'" 15 | -------------------------------------------------------------------------------- /client/settings/types.ts: -------------------------------------------------------------------------------- 1 | import * as t from 'io-ts'; 2 | 3 | export const ApiSettings = t.type({ 4 | gist: t.type({ 5 | token: t.string, 6 | }), 7 | prism: t.type({ 8 | 'line-numbers': t.boolean, 9 | 'show-invisibles': t.boolean, 10 | theme: t.string, 11 | }), 12 | }); 13 | 14 | export type ApiSettings = t.TypeOf; 15 | -------------------------------------------------------------------------------- /client/wp/notices.module.scss: -------------------------------------------------------------------------------- 1 | .notice { 2 | margin-left: 0; 3 | margin-right: 0; 4 | margin-bottom: 5px; 5 | 6 | :global(.components-notice__content) { 7 | display: flex; 8 | flex-direction: row; 9 | align-items: center; 10 | } 11 | 12 | :global(.components-spinner) { 13 | margin-top: 0; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /resources/samples/haml: -------------------------------------------------------------------------------- 1 | !!! XML 2 | %html 3 | %body 4 | %h1.jumbo{:id=>"a", :style=>'font-weight: normal', :title=>title} highlight.js 5 | /html comment 6 | -# ignore this line 7 | %ul(style='margin: 0') 8 | -items.each do |i| 9 | %i= i 10 | = variable 11 | =variable2 12 | ~ variable3 13 | ~variable4 14 | The current year is #{DataTime.now.year}. 15 | -------------------------------------------------------------------------------- /client/globals/index.ts: -------------------------------------------------------------------------------- 1 | import { GlobalsState } from './state'; 2 | 3 | export * from './actions'; 4 | export * from './context'; 5 | export * from './state'; 6 | 7 | declare global { 8 | interface Window { 9 | __GISTPEN_GLOBALS__: GlobalsState; 10 | __GISTPEN_I18N__?: { [key: string]: string }; 11 | __webpack_public_path__?: string; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /client/prism/__tests__/prism.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | import { prismSlug } from '../'; 3 | 4 | describe('prismSlug', () => { 5 | it('should use the alias', () => { 6 | expect(prismSlug('js')).toBe('javascript'); 7 | }); 8 | 9 | it('should return the slug if no alias found', () => { 10 | expect(prismSlug('hs')).toBe('hs'); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /client/wp/CheckboxControl.tsx: -------------------------------------------------------------------------------- 1 | import { toJunction } from 'brookjs'; 2 | import { CheckboxControl } from '@wordpress/components'; 3 | import { Stream } from 'kefir'; 4 | import { checked } from './actions'; 5 | 6 | const events = { 7 | onChange: (e$: Stream) => e$.map(checked), 8 | }; 9 | 10 | export default toJunction(events)(CheckboxControl); 11 | -------------------------------------------------------------------------------- /client/components/Editor/Pre.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { prismSlug } from '../../prism'; 3 | 4 | const Pre: React.FC<{ language: string }> = ({ language, children }) => ( 5 |
 9 |     {children}
10 |   
11 | ); 12 | 13 | export default Pre; 14 | -------------------------------------------------------------------------------- /client/reducers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ajax'; 2 | export * from './authors'; 3 | export * from './editor'; 4 | export * from './gist'; 5 | export * from './prism'; 6 | export * from './repo'; 7 | export * from './commits'; 8 | export * from './route'; 9 | export * from './search'; 10 | export * from './jobs'; 11 | export * from './runs'; 12 | export * from './messages'; 13 | -------------------------------------------------------------------------------- /client/wp/actions.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'typesafe-actions'; 2 | 3 | export const change = createAction('CHANGE', resolve => (value: string) => 4 | resolve({ value }), 5 | ); 6 | 7 | export const checked = createAction( 8 | 'CHECKED', 9 | resolve => (isChecked: boolean) => resolve({ isChecked }), 10 | ); 11 | 12 | export const click = createAction('CLICK'); 13 | -------------------------------------------------------------------------------- /client/css.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.lazy.css' { 2 | const css: { 3 | use(): void; 4 | unuse(): void; 5 | }; 6 | 7 | export default css; 8 | } 9 | 10 | declare module '*.module.css' { 11 | const css: Record; 12 | 13 | export default css; 14 | } 15 | 16 | declare module '*.module.scss' { 17 | const css: Record; 18 | 19 | export default css; 20 | } 21 | -------------------------------------------------------------------------------- /resources/views/repo.php: -------------------------------------------------------------------------------- 1 | '; 10 | 11 | foreach ( $data['repo']['blobs'] as $blob ) { 12 | $output .= $this->render( 'blob', [ 'blob' => $blob ] ); 13 | } 14 | 15 | $output .= ''; 16 | 17 | return $output; 18 | -------------------------------------------------------------------------------- /app/Contract/Translations.php: -------------------------------------------------------------------------------- 1 | (); 17 | -------------------------------------------------------------------------------- /client/components/SettingsPage/Header/__stories__/Header.stories.tsx: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/react'; 2 | import React from 'react'; 3 | import Header from '../'; 4 | 5 | storiesOf('Header', module) 6 | .add('default', () => ( 7 |
8 | )) 9 | .add('loading', () => ( 10 |
11 | )); 12 | -------------------------------------------------------------------------------- /app/Http/Filter/Search.php: -------------------------------------------------------------------------------- 1 | 'default', 19 | ] ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /client/helpers/i18n.ts: -------------------------------------------------------------------------------- 1 | import { sprintf } from 'sprintf-js'; 2 | 3 | export default function i18n(key: string, ...args: any[]): string { 4 | const { __GISTPEN_I18N__ = {} } = window; 5 | 6 | if (__GISTPEN_I18N__[key]) { 7 | return sprintf(__GISTPEN_I18N__[key], ...args); 8 | } 9 | 10 | return sprintf( 11 | __GISTPEN_I18N__['i18n.notfound'] || 12 | 'Translation & fallback not found for key %s', 13 | key, 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /resources/samples/powershell: -------------------------------------------------------------------------------- 1 | $initialDate = [datetime]'2013/1/8' 2 | 3 | $rollingDate = $initialDate 4 | 5 | do { 6 | $client = New-Object System.Net.WebClient 7 | $results = $client.DownloadString("http://not.a.real.url") 8 | Write-Host "$rollingDate.ToShortDateString() - $results" 9 | $rollingDate = $rollingDate.AddDays(21) 10 | $username = [System.Environment]::UserName 11 | } until ($rollingDate -ge [datetime]'2013/12/31') 12 | -------------------------------------------------------------------------------- /client/actions/author.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'typesafe-actions'; 2 | import { Author } from '../reducers'; 3 | import { AjaxError } from '../api'; 4 | 5 | export const fetchAuthorSucceeded = createAction( 6 | 'FETCH_AUTHOR_SUCCEEDED', 7 | resolve => (author: Author) => resolve({ author }), 8 | ); 9 | 10 | export const fetchAuthorFailed = createAction( 11 | 'FETCH_AUTHOR_FAILED', 12 | resolve => (err: AjaxError) => resolve(err), 13 | ); 14 | -------------------------------------------------------------------------------- /client/RootAction.ts: -------------------------------------------------------------------------------- 1 | import { ActionType } from 'typesafe-actions'; 2 | 3 | export type RootAction = ActionType< 4 | typeof import('./actions') & 5 | typeof import('./search').actions & 6 | typeof import('./block').actions & 7 | typeof import('./globals/actions') & 8 | typeof import('./snippet/actions') & 9 | typeof import('./editor/actions') & 10 | typeof import('./settings/actions') & 11 | typeof import('./me/actions') 12 | >; 13 | -------------------------------------------------------------------------------- /client/block/SetEmbed/__stories__/CreateOrChoose.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import CreateOrChoose from '../CreateOrChoose'; 3 | 4 | export default { 5 | title: 'Create or Choose', 6 | }; 7 | 8 | export const basic = () => ( 9 |
10 | 15 |
16 | ); 17 | -------------------------------------------------------------------------------- /client/deltas/__tests__/siteDelta.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | import sinon from 'sinon'; 3 | import { siteDelta } from '../siteDelta'; 4 | 5 | describe('siteDelta', () => { 6 | it('should ignore random actions', () => { 7 | const state = {}; 8 | const action = { 9 | type: 'RANDOM', 10 | }; 11 | expect(siteDelta({ ajax$: sinon.stub() })).toEmitFromDelta([], send => { 12 | send(action, state); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /client/deltas/__tests__/userDelta.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | import sinon from 'sinon'; 3 | import { userDelta } from '../userDelta'; 4 | 5 | describe('userDelta', () => { 6 | it('should ignore random actions', () => { 7 | const state = {}; 8 | const action = { 9 | type: 'RANDOM', 10 | }; 11 | expect(userDelta({ ajax$: sinon.stub() })).toEmitFromDelta([], send => { 12 | send(action, state); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /app/Jobs/Status.php: -------------------------------------------------------------------------------- 1 | { 6 | it('should ignore random actions', () => { 7 | const state = {}; 8 | const action = { 9 | type: 'RANDOM', 10 | }; 11 | expect(searchDelta({ ajax$: sinon.stub() })).toEmitFromDelta([], send => { 12 | send(action, state); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /client/components/SettingsPage/Jobs/__stories__/Jobs.stories.tsx: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/react'; 2 | import React from 'react'; 3 | import Jobs from '../'; 4 | 5 | storiesOf('Jobs', module).add('default', () => ( 6 | 18 | )); 19 | -------------------------------------------------------------------------------- /resources/samples/jade: -------------------------------------------------------------------------------- 1 | !!! 2 | html(lang="en") 3 | head 4 | meta(charset="utf-8") 5 | title CSS Hover Effect on Vertical Menu 6 | link(rel="stylesheet", href="style.css") 7 | body 8 | ul.leftmenu 9 | li 10 | a(href="http://learnwebtutorials.com/tutorial-install-node-js-windows") Learn NodeJS 11 | li 12 | a(href="http://learnwebtutorials.com/wordpress-tutorials") Learn WordPress 13 | li 14 | a(href="http://learnwebtutorials.com/php-tutorials") Learn PHP 15 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | name: Node.js 2 | 3 | on: 4 | push: 5 | branches: [ next ] 6 | pull_request: 7 | branches: [ next ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Use Node.js 12 17 | uses: actions/setup-node@v2 18 | with: 19 | node-version: 12 20 | cache: 'npm' 21 | - run: npm ci 22 | - run: npm run build 23 | - run: npm test 24 | -------------------------------------------------------------------------------- /resources/samples/markdown: -------------------------------------------------------------------------------- 1 | # hello world 2 | 3 | you can write text [with links](http://example.com) inline or [link references][1]. 4 | 5 | * one _thing_ has *em*phasis 6 | * two __things__ are **bold** 7 | 8 | [1]: http://example.com 9 | 10 | --- 11 | 12 | hello world 13 | =========== 14 | 15 | 16 | 17 | > markdown is so cool 18 | 19 | so are code segments 20 | 21 | 1. one thing (yeah!) 22 | 2. two thing `i can write code`, and `more` wipee! 23 | -------------------------------------------------------------------------------- /resources/samples/twig: -------------------------------------------------------------------------------- 1 | {% if posts|length %} 2 | {% for article in articles %} 3 |
4 | {{ article.title|upper() }} 5 | 6 | {# outputs 'WELCOME' #} 7 |
8 | {% endfor %} 9 | {% endif %} 10 | 11 | {% set user = json_encode(user) %} 12 | 13 | {{ random(['apple', 'orange', 'citrus']) }} 14 | 15 | {{ include(template_from_string("Hello {{ name }}")) }} 16 | 17 | 18 | {# 19 | Comments may be long and multiline. 20 | Markup is not highlighted within comments. 21 | #} 22 | -------------------------------------------------------------------------------- /test/Integration/Console/Repo/TestCase.php: -------------------------------------------------------------------------------- 1 | command = $this->app->make( RepoCommand::class ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client/search/selectors.tsx: -------------------------------------------------------------------------------- 1 | import { State, HasSnippet, HasError } from './state'; 2 | 3 | export const isLoading = (state: State) => 4 | state.status === 'searching' || state.status === 'researching'; 5 | 6 | export const hasSnippets = (state: State): state is HasSnippet => 7 | state.status === 'found' || 8 | state.status === 'researching' || 9 | state.status === 'reerror'; 10 | 11 | export const hasError = (state: State): state is HasError => 12 | state.status === 'error' || state.status === 'reerror'; 13 | -------------------------------------------------------------------------------- /test/Integration/Console/Blob/TestCase.php: -------------------------------------------------------------------------------- 1 | command = $this->app->make( BlobCommand::class ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client/actions/highlighting.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'typesafe-actions'; 2 | 3 | export const themeChange = createAction( 4 | 'THEME_CHANGE', 5 | resolve => (value: string) => resolve({ value }), 6 | ); 7 | 8 | export const lineNumbersChange = createAction( 9 | 'LINE_NUMBERS_CHANGE', 10 | resolve => (value: boolean) => resolve({ value }), 11 | ); 12 | 13 | export const showInvisiblesChange = createAction( 14 | 'SHOW_INVISIBLES_CHANGE', 15 | resolve => (value: boolean) => resolve({ value }), 16 | ); 17 | -------------------------------------------------------------------------------- /client/me/actions.ts: -------------------------------------------------------------------------------- 1 | import { DeepPartial } from 'redux'; 2 | import { createAsyncAction } from 'typesafe-actions'; 3 | import { AjaxError } from '../api'; 4 | import { ApiMe } from './types'; 5 | 6 | export const fetchMe = createAsyncAction( 7 | 'FETCH_ME_REQUESTED', 8 | 'FETCH_ME_SUCCEEDED', 9 | 'FETCH_ME_FAILED', 10 | )(); 11 | 12 | export const saveMe = createAsyncAction( 13 | 'SAVE_ME_REQUESTED', 14 | 'SAVE_ME_SUCCEEDED', 15 | 'SAVE_ME_FAILED', 16 | ), ApiMe, AjaxError>(); 17 | -------------------------------------------------------------------------------- /resources/samples/csharp: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | #pragma warning disable 414, 3021 4 | 5 | public class Program 6 | { 7 | /// The entry point to the program. 8 | public static int Main(string[] args) 9 | { 10 | Console.WriteLine("Hello, World!"); 11 | string s = @"This 12 | ""string"" 13 | spans 14 | multiple 15 | lines!"; 16 | return 0; 17 | } 18 | } 19 | 20 | async Task AccessTheWebAsync() 21 | { 22 | // ... 23 | string urlContents = await getStringTask; 24 | return urlContents.Length; 25 | } 26 | -------------------------------------------------------------------------------- /client/block/Shortcode.tsx: -------------------------------------------------------------------------------- 1 | import { Maybe } from 'brookjs'; 2 | import React from 'react'; 3 | 4 | const maybeAttribute = (value: Maybe, attribute: string) => 5 | value != null ? ` ${attribute}="${value}"` : ''; 6 | 7 | export const Shortcode: React.FC<{ 8 | blobId: number; 9 | highlight?: Maybe; 10 | offset?: Maybe; 11 | }> = ({ blobId, highlight, offset }) => ( 12 | <> 13 | [gistpen id="{blobId}"{maybeAttribute(highlight, 'highlight')} 14 | {maybeAttribute(offset, 'offset')}] 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /client/search/ResultsPlaceholder.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SearchResult from './SearchResult'; 3 | 4 | export const ResultsPlaceholder: React.FC<{ 5 | label: string; 6 | }> = ({ label }) => { 7 | return ( 8 | <> 9 | 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /client/block/__tests__/state.spec.ts: -------------------------------------------------------------------------------- 1 | import { reducer } from '../state'; 2 | 3 | describe('state', () => { 4 | describe('reducer', () => { 5 | it('should return the same state on random actions', () => { 6 | const initialState = { 7 | status: 'set-embed', 8 | repoId: null, 9 | blobId: null, 10 | highlight: null, 11 | offset: null, 12 | } as const; 13 | expect(reducer(initialState, { type: '@@RANDOM' } as any)).toEqual( 14 | initialState, 15 | ); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /client/pages/edit/View.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Commits, EditPage } from '../../components'; 3 | 4 | const View: React.FC<{ 5 | route: string | null; 6 | edit: React.ComponentProps; 7 | commits: React.ComponentProps; 8 | }> = ({ route, edit, commits }) => { 9 | switch (route) { 10 | case 'editor': 11 | return ; 12 | case 'commits': 13 | return ; 14 | default: 15 | return null; 16 | } 17 | }; 18 | 19 | export default View; 20 | -------------------------------------------------------------------------------- /resources/samples/js: -------------------------------------------------------------------------------- 1 | function $initHighlight(block, flags) { 2 | try { 3 | if (block.className.search(/\bno\-highlight\b/) != -1) 4 | return processBlock(block.function, true, 0x0F) + ' class=""'; 5 | } catch (e) { 6 | /* handle exception */ 7 | var e4x = 8 |
Example 9 |

1234

; 10 | } 11 | for (var i = 0 / 2; i < classes.length; i++) { // "0 / 2" should not be parsed as regexp 12 | if (checkCondition(classes[i]) === undefined) 13 | return /\d+[\s/]/g; 14 | } 15 | console.log(Array.every(classes, Boolean)); 16 | } 17 | -------------------------------------------------------------------------------- /bin/docker-compose.override.yml.template: -------------------------------------------------------------------------------- 1 | services: 2 | wordpress-develop: 3 | volumes: 4 | - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% 5 | php: 6 | volumes: 7 | - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% 8 | cli: 9 | volumes: 10 | - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% 11 | phpunit: 12 | volumes: 13 | - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% 14 | -------------------------------------------------------------------------------- /resources/samples/latex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{article} 2 | % options include 12pt or 11pt or 10pt 3 | % classes include article, report, book, letter, thesis 4 | 5 | \title{This is the title} 6 | \author{Author One \\ Author Two} 7 | \date{29 February 2004} 8 | 9 | \begin{document} 10 | \maketitle 11 | 12 | This is the content of this document. 13 | 14 | This is the 2nd paragraph. 15 | Here is an inline formula: 16 | $ V = \frac{4 \pi r^3}{3} $. 17 | And appearing immediately below 18 | is a displayed formula: 19 | $$ V = \frac{4 \pi r^3}{3} $$ 20 | \end{document} 21 | -------------------------------------------------------------------------------- /app/Params/demo-code: -------------------------------------------------------------------------------- 1 | function initHighlight(block, flags) { 2 | try { 3 | if (block.className.search(/\bno\-highlight\b/) != -1) 4 | return processBlock(block.function, true, 0x0f) + ' class=""'; 5 | } catch (e) { 6 | /* handle exception */ 7 | const e4x = `
Example 8 |

1234

`; 9 | } 10 | for (let i = 0 / 2; i < classes.length; i++) { 11 | // "0 / 2" should not be parsed as regexp 12 | if (checkCondition(classes[i]) === undefined) return /\d+[\s/]/g; 13 | } 14 | console.log(Array.every(classes, Boolean)); 15 | } 16 | -------------------------------------------------------------------------------- /client/components/Blob/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classNames from 'classnames'; 3 | import Code from './Code'; 4 | import { Props } from './types'; 5 | 6 | const propsToClassName = (prism: Props['prism']) => 7 | classNames({ 8 | gistpen: true, 9 | 'line-numbers': prism['line-numbers'], 10 | }); 11 | 12 | const Blob: React.FC = props => ( 13 |
17 |     
18 |   
19 | ); 20 | 21 | export default Blob; 22 | -------------------------------------------------------------------------------- /client/settings/actions.ts: -------------------------------------------------------------------------------- 1 | import { createAsyncAction } from 'typesafe-actions'; 2 | import { AjaxError, PatchBody } from '../api'; 3 | import { ApiSettings } from './types'; 4 | 5 | export const fetchSettings = createAsyncAction( 6 | 'FETCH_SETTINGS_REQUESTED', 7 | 'FETCH_SETTINGS_SUCCEEDED', 8 | 'FETCH_SETTINGS_FAILED', 9 | )(); 10 | 11 | export const saveSettings = createAsyncAction( 12 | 'SAVE_SETTINGS_REQUESTED', 13 | 'SAVE_SETTINGS_SUCCEEDED', 14 | 'SAVE_SETTINGS_FAILED', 15 | ), ApiSettings, AjaxError>(); 16 | -------------------------------------------------------------------------------- /test/Unit/Client/GistTest.php: -------------------------------------------------------------------------------- 1 | gist = $this->app->make( Gist::class ); 18 | } 19 | 20 | public function test_all_returns_error_with_no_token() { 21 | $response = $this->gist->all(); 22 | 23 | $this->assertWPError( $response ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /resources/samples/actionscript: -------------------------------------------------------------------------------- 1 | package org.example.dummy { 2 | import org.dummy.*; 3 | 4 | /*define package inline interface*/ 5 | public interface IFooBarzable { 6 | public function foo(... pairs):Array; 7 | } 8 | 9 | public class FooBar implements IFooBarzable { 10 | static private var cnt:uint = 0; 11 | private var bar:String; 12 | 13 | //constructor 14 | public function TestBar(bar:String):void { 15 | bar = bar; 16 | ++cnt; 17 | } 18 | 19 | public function foo(... pairs):Array { 20 | pairs.push(bar); 21 | return pairs; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /resources/samples/smarty: -------------------------------------------------------------------------------- 1 | //If condition 2 | {if $name eq "smarty"} 3 | Its smarty 4 | {/elseif $name eq "php"} 5 | Its php 6 | {/else} 7 | Its neither smarty nor php 8 | {/if} 9 | 10 | //foreach loop 11 | {foreach $articles as $article} 12 |

{$article->title}

13 |

{$article->description}

14 | {/foreach} 15 | 16 | //section, alternative of foreach 17 | {section name=name loop=$items} 18 | id: {$items[name]}
19 | {/section} 20 | 21 | //generate select option easily 22 | {html_options values=$id output=$items selected="2"} 23 | -------------------------------------------------------------------------------- /resources/samples/swift: -------------------------------------------------------------------------------- 1 | extension MyClass : Interface { 2 | class func unarchiveFromFile
(file : A, (Int,Int) -> B) -> SKNode? { 3 | let path: String = bundle.pathForResource(file, ofType: "file\(name + 5).txt") 4 | let funnyNumber = 3 + 0xC2.15p2 * (1_000_000.000_000_1 - 000123.456) + 0o21 5 | var sceneData = NSData.dataWithContentsOfFile(path, options: .DataReadingMappedIfSafe, error: nil) 6 | /* a comment /* with a nested comment */ and the end */ 7 | } 8 | @objc override func shouldAutorotate() { 9 | return true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /resources/samples/bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ###### BEGIN CONFIG 4 | ACCEPTED_HOSTS="/root/.hag_accepted.conf" 5 | BE_VERBOSE=false 6 | ###### END CONFIG 7 | 8 | if [ "$UID" -ne 0 ] 9 | then 10 | echo "Superuser rights is required" 11 | echo 'Printing the # sign' 12 | exit 2 13 | fi 14 | 15 | if test $# -eq 0 16 | then 17 | elif test [ $1 == 'start' ] 18 | else 19 | fi 20 | 21 | genApacheConf(){ 22 | if [[ "$2" = "www" ]] 23 | then 24 | full_domain=$1 25 | else 26 | full_domain=$2.$1 27 | fi 28 | host_root="${APACHE_HOME_DIR}$1/$2/$(title)" 29 | echo -e "# Host $1/$2 :" 30 | } 31 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "lib": ["dom", "es2017"], 5 | "allowJs": false, 6 | "skipLibCheck": false, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true, 16 | "jsx": "react" 17 | }, 18 | "include": [ 19 | "client", 20 | "commands", 21 | "e2e" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /client/components/SearchPopup/index.scss: -------------------------------------------------------------------------------- 1 | .wpgp-search-container { 2 | display: flex; 3 | flex-direction: column; 4 | 5 | .wpgp-search-form { 6 | display: flex; 7 | flex-direction: row; 8 | margin-top: 5px; 9 | margin-bottom: 9px; 10 | } 11 | 12 | .wpgp-search-label { 13 | text-align: right; 14 | padding-right: 5px; 15 | vertical-align: text-top; 16 | } 17 | 18 | .wpgp-search-result { 19 | padding: 5px 0; 20 | } 21 | 22 | .wpgp-search-result-title { 23 | cursor: pointer; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /client/components/Repo/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Blob from '../Blob'; 3 | 4 | type RepoProps = { 5 | blobs: Array<{ 6 | ID: string; 7 | code: string; 8 | filename: string; 9 | language: string; 10 | }>; 11 | prism: { 12 | theme: string; 13 | 'line-numbers': boolean; 14 | 'show-invisibles': boolean; 15 | }; 16 | }; 17 | 18 | const Repo: React.FC = ({ blobs, prism }) => ( 19 |
20 | {blobs.map(blob => ( 21 | 22 | ))} 23 |
24 | ); 25 | 26 | export default Repo; 27 | -------------------------------------------------------------------------------- /client/components/SettingsPage/Messages/__stories__/Messages.stories.tsx: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/react'; 2 | import React from 'react'; 3 | import Messages from '../'; 4 | 5 | storiesOf('Messages', module).add('default', () => ( 6 | 22 | )); 23 | -------------------------------------------------------------------------------- /app/Contract/Templating.php: -------------------------------------------------------------------------------- 1 | 9 | render(element, { 10 | wrapper: RootJunction as any, 11 | }), 12 | snapshotSerializers: [ 13 | { 14 | print: (val, serialize) => serialize(val.container.firstChild), 15 | test: val => val && val.hasOwnProperty('container'), 16 | }, 17 | ], 18 | }); 19 | -------------------------------------------------------------------------------- /client/deltas/webpackDelta.ts: -------------------------------------------------------------------------------- 1 | import { Observable, stream } from 'kefir'; 2 | import { GlobalsState } from '../globals'; 3 | import { RootAction } from '../RootAction'; 4 | 5 | type WebpackDeltaState = { 6 | globals: GlobalsState; 7 | }; 8 | 9 | export const webpackDelta = ( 10 | actions$: Observable, 11 | state$: Observable, 12 | ): Observable => 13 | state$.take(1).flatMap(props => 14 | stream(emitter => { 15 | window.__webpack_public_path__ = props.globals.url + 'resources/assets/'; 16 | 17 | emitter.end(); 18 | }), 19 | ); 20 | -------------------------------------------------------------------------------- /resources/samples/css: -------------------------------------------------------------------------------- 1 | @media screen and (-webkit-min-device-pixel-ratio: 0) { 2 | body:first-of-type pre::after { 3 | content: 'highlight: ' attr(class); 4 | } 5 | body { 6 | background: linear-gradient(45deg, blue, red); 7 | } 8 | } 9 | 10 | @import url('print.css'); 11 | @page:right { 12 | margin: 1cm 2cm 1.3cm 4cm; 13 | } 14 | 15 | @font-face { 16 | font-family: Chunkfive; src: url('Chunkfive.otf'); 17 | } 18 | 19 | div.text, 20 | #content, 21 | li[lang=ru] { 22 | font: Tahoma, Chunkfive, sans-serif; 23 | background: url('hatch.png') /* wtf? */; color: #F0F0F0 !important; 24 | width: 100%; 25 | } 26 | -------------------------------------------------------------------------------- /client/components/Editor/types.ts: -------------------------------------------------------------------------------- 1 | import { Toggle } from '../../api'; 2 | import { Cursor } from '../../editor/types'; 3 | 4 | export type Props = { 5 | code: string; 6 | filename: string; 7 | cursor: Cursor; 8 | languages: Array<{ 9 | value: string; 10 | label: string; 11 | }>; 12 | language: string; 13 | theme: string; 14 | invisibles: Toggle; 15 | embedCode?: string; 16 | onFilenameChange: (e: React.ChangeEvent) => void; 17 | onLanguageChange: (e: React.ChangeEvent) => void; 18 | onDeleteClick: (e: React.MouseEvent) => void; 19 | }; 20 | -------------------------------------------------------------------------------- /client/selectors/api.ts: -------------------------------------------------------------------------------- 1 | import { AjaxOptions } from 'kefir-ajax'; 2 | import { UserDeltaState } from '../deltas'; 3 | 4 | export const selectUserAjaxOpts = (state: UserDeltaState): AjaxOptions => ({ 5 | method: 'PATCH', 6 | body: JSON.stringify({ 7 | editor: { 8 | theme: state.editor.theme, 9 | invisibles_enabled: state.editor.invisibles, 10 | tabs_enabled: state.editor.tabs, 11 | indent_width: state.editor.width, 12 | }, 13 | }), 14 | credentials: 'include', 15 | headers: { 16 | 'X-WP-Nonce': state.globals.nonce, 17 | 'Content-Type': 'application/json', 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /client/globals/context.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext, useEffect } from 'react'; 2 | import { setAutoloaderPath } from '../prism'; 3 | import { GlobalsState, defaultGlobals } from './state'; 4 | 5 | const GlobalsContext = createContext(defaultGlobals); 6 | 7 | export const useGlobals = () => { 8 | const globals = useContext(GlobalsContext); 9 | 10 | useEffect(() => { 11 | setAutoloaderPath( 12 | (__webpack_public_path__ = globals.url + 'resources/assets/'), 13 | ); 14 | }, [globals.url]); 15 | 16 | return globals; 17 | }; 18 | export const GlobalsProvider = GlobalsContext.Provider; 19 | -------------------------------------------------------------------------------- /client/search/SearchResult.module.scss: -------------------------------------------------------------------------------- 1 | .popover { 2 | :global(.components-popover__content) { 3 | background: transparent; 4 | z-index: 100; 5 | } 6 | } 7 | 8 | .placeholder:global(.components-placeholder.components-placeholder) { 9 | min-height: unset; 10 | margin-bottom: 5px; 11 | flex-direction: row; 12 | justify-content: space-between; 13 | align-items: center; 14 | width: unset; 15 | 16 | :global(.components-placeholder__label) { 17 | margin-bottom: 0; 18 | } 19 | 20 | :global(.components-placeholder__fieldset) { 21 | width: unset; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/Integration/Console/Site/TestCase.php: -------------------------------------------------------------------------------- 1 | command = $this->app->make( SiteCommand::class ); 18 | $this->options = $this->app->make( SiteOptions::class ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/Unit/Console/Binding.php: -------------------------------------------------------------------------------- 1 | binding = $this->app->make( Binding::class ); 18 | } 19 | 20 | public function test_registers_command() { 21 | $mock = \Mockery::mock( 'overload:WP_CLI' ); 22 | $mock->shouldReceive( 'add_command' ); 23 | 24 | $this->binding->register_command(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /client/pages/settings/router.ts: -------------------------------------------------------------------------------- 1 | import sheetRouter from 'sheet-router'; 2 | import { routeChange } from '../../actions'; 3 | import { RouteParts } from '../../reducers'; 4 | 5 | export default sheetRouter({ default: '/highlighting' }, [ 6 | ['/highlighting', () => routeChange('highlighting')], 7 | ['/accounts', () => routeChange('accounts')], 8 | [ 9 | '/jobs', 10 | () => routeChange('jobs'), 11 | [ 12 | [ 13 | '/:job', 14 | (params: RouteParts) => routeChange('jobs', params), 15 | [['/:run', (params: RouteParts) => routeChange('jobs', params)]], 16 | ], 17 | ], 18 | ], 19 | ]); 20 | -------------------------------------------------------------------------------- /client/deltas/__tests__/webpackDelta.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | import { webpackDelta } from '../webpackDelta'; 3 | 4 | describe('webpackDelta', () => { 5 | it('should set public path on initial state', () => { 6 | const state = { 7 | globals: { 8 | url: 'https://test.dev/', 9 | }, 10 | }; 11 | const action = { 12 | type: 'INIT', 13 | }; 14 | expect(webpackDelta).toEmitFromDelta([[0, KTU.end()]], send => { 15 | send(action, state); 16 | }); 17 | 18 | expect(window.__webpack_public_path__).toBe( 19 | 'https://test.dev/resources/assets/', 20 | ); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /resources/samples/go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | const ( 9 | Sunday = iota 10 | numberOfDays // this constant is not exported 11 | ) 12 | 13 | type Foo interface { 14 | FooFunc(int, float32) (complex128, []int) 15 | } 16 | 17 | type Bar struct { 18 | os.File /* multi-line 19 | comment */ 20 | PublicData chan int 21 | } 22 | 23 | func main() { 24 | ch := make(chan int) 25 | ch <- 1 26 | x, ok := <- ch 27 | ok = true 28 | float_var := 1.0e10 29 | defer fmt.Println('\'') 30 | defer fmt.Println(`exitting now\`) 31 | var fv1 float64 = 0.75 32 | go println(len("hello world!")) 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | # WordPress Coding Standards 5 | # http://make.wordpress.org/core/handbook/coding-standards/ 6 | 7 | root = true 8 | 9 | [*] 10 | charset = utf-8 11 | end_of_line = lf 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | indent_style = tab 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false 18 | 19 | [*.{json,babelrc,js,ts,tsx}] 20 | indent_style = space 21 | indent_size = 2 22 | 23 | [*.{yml,apib,hbs,scss}] 24 | indent_style = space 25 | indent_size = 4 26 | 27 | [*.txt,wp-config-sample.php] 28 | end_of_line = crlf 29 | -------------------------------------------------------------------------------- /app/Http/Filter/RepoUpdate.php: -------------------------------------------------------------------------------- 1 | true, 26 | ]; 27 | 28 | return $rules; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /client/editor/types.tsx: -------------------------------------------------------------------------------- 1 | import { ActionType } from 'typesafe-actions'; 2 | import * as actions from './actions'; 3 | 4 | export type PrismLib = typeof import('prismjs'); 5 | 6 | export type EditorAction = ActionType; 7 | 8 | export type Cursor = null | [number, number]; 9 | 10 | export type EditorValue = { 11 | code: string; 12 | cursor: Cursor; 13 | }; 14 | 15 | export type EditorIndentValue = EditorValue & { 16 | inverse: boolean; 17 | }; 18 | 19 | export type EditorSnapshot = { 20 | code: string; 21 | cursor: Cursor; 22 | }; 23 | 24 | export type EditorHistory = { 25 | undo: EditorSnapshot[]; 26 | redo: EditorSnapshot[]; 27 | }; 28 | -------------------------------------------------------------------------------- /test/Unit/LifecycleTest.php: -------------------------------------------------------------------------------- 1 | app->make( Lifecycle::class ); 9 | 10 | $lifecyle->activate(); 11 | 12 | $this->assertEquals( $this->app->get( 'version' ), get_option( 'wp_gistpen_version' ) ); 13 | $this->assertEquals( 'done', get_option( '_wpgp_activated' ) ); 14 | } 15 | 16 | public function test_should_flush_on_dectivation() { 17 | $lifecyle = $this->app->make( Lifecycle::class ); 18 | 19 | $lifecyle->deactivate(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/Unit/Register/Router.php: -------------------------------------------------------------------------------- 1 | register = $this->app->make( Register::class ); 19 | } 20 | 21 | public function test_should_register_routes() { 22 | $this->register->add_routes( $this->app->get( CoreRouter::class ) ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /resources/samples/sql: -------------------------------------------------------------------------------- 1 | 2 | BEGIN; 3 | CREATE TABLE "topic" ( 4 | -- This is the greatest table of all time 5 | "id" serial NOT NULL PRIMARY KEY, 6 | "forum_id" integer NOT NULL, 7 | "subject" varchar(255) NOT NULL -- Because nobody likes an empty subject 8 | ); 9 | ALTER TABLE "topic" ADD CONSTRAINT forum_id FOREIGN KEY ("forum_id") REFERENCES "forum" ("id"); 10 | 11 | -- Initials 12 | insert into "topic" ("forum_id", "subject") values (2, 'D''artagnian'); 13 | 14 | select /* comment */ count(*) from cicero_forum; 15 | 16 | -- this line lacks ; at the end to allow people to be sloppy and omit it in one-liners 17 | /* 18 | but who cares? 19 | */ 20 | COMMIT 21 | -------------------------------------------------------------------------------- /app/Http/Filter/RepoResource.php: -------------------------------------------------------------------------------- 1 | array( 24 | 'required' => true, 25 | 'type' => 'integer', 26 | ), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /client/components/SettingsPage/Accounts/__tests__/Accounts.spec.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | import React from 'react'; 3 | import { fireEvent } from '@testing-library/react'; 4 | import { gistTokenChange } from '../../../../actions'; 5 | import Accounts from '../'; 6 | 7 | describe('Accounts', () => { 8 | it('should emit action when clicked', () => { 9 | expect().toEmitFromJunction( 10 | [[0, KTU.value(gistTokenChange('abc'))]], 11 | ({ queryByTestId }) => { 12 | const input = queryByTestId('gist-token') as Element; 13 | 14 | fireEvent.change(input, { target: { value: 'abc' } }); 15 | }, 16 | ); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /client/components/SettingsPage/Runs/__stories__/Runs.stories.tsx: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/react'; 2 | import React from 'react'; 3 | import Runs from '../'; 4 | 5 | storiesOf('Runs', module).add('default', () => ( 6 | 25 | )); 26 | -------------------------------------------------------------------------------- /client/reducers/gist.ts: -------------------------------------------------------------------------------- 1 | import { getType } from 'typesafe-actions'; 2 | import { EddyReducer } from 'brookjs'; 3 | import { RootAction } from '../RootAction'; 4 | import { gistTokenChange } from '../actions'; 5 | 6 | export type GistState = { 7 | token: string; 8 | }; 9 | 10 | const defaultState: GistState = { 11 | token: '', 12 | }; 13 | 14 | export const gistReducer: EddyReducer = ( 15 | state = defaultState, 16 | action, 17 | ) => { 18 | switch (action.type) { 19 | case getType(gistTokenChange): 20 | return { 21 | ...state, 22 | token: action.payload.value, 23 | }; 24 | default: 25 | return state; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /client/pages/settings/state.ts: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'brookjs'; 2 | import { StateType } from 'typesafe-actions'; 3 | import { 4 | ajaxReducer, 5 | routeReducer, 6 | prismReducer, 7 | gistReducer, 8 | jobsReducer, 9 | runsReducer, 10 | messagesReducer, 11 | } from '../../reducers'; 12 | import { globalsReducer } from '../../globals'; 13 | 14 | export const reducer = combineReducers({ 15 | ajax: ajaxReducer, 16 | globals: globalsReducer, 17 | route: routeReducer, 18 | prism: prismReducer, 19 | gist: gistReducer, 20 | jobs: jobsReducer, 21 | runs: runsReducer, 22 | messages: messagesReducer, 23 | }); 24 | 25 | export type State = StateType[0]; 26 | -------------------------------------------------------------------------------- /client/actions/commits.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'typesafe-actions'; 2 | import { ApiCommits } from '../deltas'; 3 | import { AjaxError } from '../api'; 4 | 5 | export const commitsFetchStarted = createAction('COMMITS_FETCH_STARTED'); 6 | 7 | export const commitsFetchSucceeded = createAction( 8 | 'COMMITS_FETCH_SUCCEEDED', 9 | resolve => (response: ApiCommits) => resolve({ response }), 10 | ); 11 | 12 | export const commitsFetchFailed = createAction( 13 | 'COMMITS_FETCH_FAILED', 14 | resolve => (err: AjaxError) => resolve(err), 15 | ); 16 | 17 | export const commitClick = createAction( 18 | 'COMMIT_CLICK', 19 | resolve => (key: string | number) => resolve(undefined, { key }), 20 | ); 21 | -------------------------------------------------------------------------------- /client/reducers/repo.ts: -------------------------------------------------------------------------------- 1 | import { Nullable } from 'typescript-nullable'; 2 | import { getType } from 'typesafe-actions'; 3 | import { EddyReducer } from 'brookjs'; 4 | import { repoSaveSucceeded } from '../actions'; 5 | import { RootAction } from '../RootAction'; 6 | import { ApiRepo } from '../snippet'; 7 | 8 | export type RepoState = Nullable; 9 | 10 | const defaultState: RepoState = null; 11 | 12 | export const repoReducer: EddyReducer = ( 13 | state = defaultState, 14 | action, 15 | ) => { 16 | switch (action.type) { 17 | case getType(repoSaveSucceeded): 18 | return action.payload.response; 19 | default: 20 | return state; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /test/Integration/Console/User/TestCase.php: -------------------------------------------------------------------------------- 1 | command = $this->app->make( UserCommand::class ); 23 | $this->options = $this->app->make( UserOptions::class ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/helpers.php: -------------------------------------------------------------------------------- 1 | addDefinitions( dirname( __DIR__ ) . '/resources/config/container.php' ); 17 | 18 | $container = $builder->build(); 19 | } 20 | 21 | return $container; 22 | } 23 | 24 | /** 25 | * Boot the application. 26 | */ 27 | function boot() { 28 | add_action( 'plugins_loaded', [ container()->get( Loader::class ), 'run' ] ); 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Filter/BlobUpdate.php: -------------------------------------------------------------------------------- 1 | true, 26 | ]; 27 | $rules['blob_id'] = [ 28 | 'required' => true, 29 | ]; 30 | 31 | return $rules; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /bin/reset-docker-db.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docker-compose exec db mysql -uwordpress -pdbpass -e 'DROP database wordpress; CREATE database wordpress;' 4 | docker-compose exec app wp core install --allow-root \ 5 | --url="http://localhost:3000" \ 6 | --title="wp-gistpen test site" \ 7 | --admin_user="admin" \ 8 | --admin_email="admin@example.test"\ 9 | --admin_password="wpgppass1"; 10 | docker-compose exec app wp plugin activate wp-gistpen --allow-root 11 | docker-compose exec app wp plugin delete akismet --allow-root 12 | docker-compose exec app wp plugin delete hello.php --allow-root 13 | docker-compose exec app wp plugin install classic-editor --allow-root 14 | docker-compose exec app wp rewrite structure '/%postname%/' --allow-root 15 | -------------------------------------------------------------------------------- /resources/samples/scheme: -------------------------------------------------------------------------------- 1 | ;; Calculation of Hofstadter's male and female sequences as a list of pairs 2 | 3 | (define (hofstadter-male-female n) 4 | (letrec ((female (lambda (n) 5 | (if (= n 0) 6 | 1 7 | (- n (male (female (- n 1))))))) 8 | (male (lambda (n) 9 | (if (= n 0) 10 | 0 11 | (- n (female (male (- n 1)))))))) 12 | (let loop ((i 0)) 13 | (if (> i n) 14 | '() 15 | (cons (cons (female i) 16 | (male i)) 17 | (loop (+ i 1))))))) 18 | 19 | (hofstadter-male-female 8) 20 | 21 | (define (find-first func lst) 22 | (call-with-current-continuation 23 | (lambda (return-immediately) 24 | (for-each (lambda (x) 25 | (if (func x) 26 | (return-immediately x))) 27 | lst) 28 | #f))) 29 | -------------------------------------------------------------------------------- /resources/samples/gherkin: -------------------------------------------------------------------------------- 1 | # language: en 2 | Feature: Addition 3 | In order to avoid silly mistakes 4 | As a math idiot 5 | I want to be told the sum of two numbers 6 | 7 | @this_is_a_tag 8 | Scenario Outline: Add two numbers 9 | * I have a calculator 10 | Given I have entered into the calculator 11 | And I have entered into the calculator 12 | When I press
28 | 29 | 30 | ); 31 | 32 | const events = { 33 | onClick: (evt$: Observable) => 34 | evt$.map(jobDispatchClick).debounce(200), 35 | }; 36 | 37 | export default toJunction(events)(Row); 38 | -------------------------------------------------------------------------------- /app/Params/Gist.php: -------------------------------------------------------------------------------- 1 | site = $site; 26 | } 27 | 28 | /** 29 | * Add prism key to params array. 30 | * 31 | * @param array $params Current params array. 32 | * 33 | * @return array 34 | */ 35 | public function apply_gist( $params ) { 36 | $params['gist'] = $this->site->get( 'gist' ); 37 | 38 | return $params; 39 | } 40 | /** 41 | * {@inheritDoc} 42 | */ 43 | public function filter_hooks() { 44 | return array( 45 | array( 46 | 'hook' => 'params.state.settings', 47 | 'method' => 'apply_gist', 48 | ), 49 | array( 50 | 'hook' => 'params.props.settings', 51 | 'method' => 'apply_gist', 52 | ), 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /client/selectors/dom.ts: -------------------------------------------------------------------------------- 1 | export function selectSelectionStart(node: Element): number { 2 | const selection = getSelection(); 3 | 4 | if (selection && selection.rangeCount) { 5 | const range = selection.getRangeAt(0); 6 | let element: Node | null = range.startContainer; 7 | let container: Node | null = element; 8 | let offset = range.startOffset; 9 | 10 | if (!container || !(node.compareDocumentPosition(element) & 0x10)) { 11 | return 0; 12 | } 13 | 14 | do { 15 | while ((element = element.previousSibling)) { 16 | if (element.textContent) { 17 | offset += element.textContent.length; 18 | } 19 | } 20 | 21 | element = container = container.parentNode; 22 | } while (container && element && element !== node); 23 | 24 | return offset; 25 | } else { 26 | return 0; 27 | } 28 | } 29 | 30 | export function selectSelectionEnd(node: Element): number { 31 | const selection = getSelection(); 32 | 33 | if (selection && selection.rangeCount) { 34 | return ( 35 | selectSelectionStart(node) + selection.getRangeAt(0).toString().length 36 | ); 37 | } else { 38 | return 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /client/reducers/prism.ts: -------------------------------------------------------------------------------- 1 | import { getType } from 'typesafe-actions'; 2 | import { EddyReducer } from 'brookjs'; 3 | import { RootAction } from '../RootAction'; 4 | import { 5 | themeChange, 6 | lineNumbersChange, 7 | showInvisiblesChange, 8 | } from '../actions'; 9 | 10 | export type PrismState = { 11 | theme: string; 12 | 'line-numbers': boolean; 13 | 'show-invisibles': boolean; 14 | }; 15 | 16 | export const defaultPrism: PrismState = { 17 | theme: 'default', 18 | 'line-numbers': false, 19 | 'show-invisibles': false, 20 | }; 21 | 22 | export const prismReducer: EddyReducer = ( 23 | state = defaultPrism, 24 | action, 25 | ) => { 26 | switch (action.type) { 27 | case getType(themeChange): 28 | return { 29 | ...state, 30 | theme: action.payload.value, 31 | }; 32 | case getType(lineNumbersChange): 33 | return { 34 | ...state, 35 | 'line-numbers': action.payload.value, 36 | }; 37 | case getType(showInvisiblesChange): 38 | return { 39 | ...state, 40 | 'show-invisibles': action.payload.value, 41 | }; 42 | default: 43 | return state; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /test/Unit/Params/EditorTest.php: -------------------------------------------------------------------------------- 1 | editor = $this->app->make( Editor::class ); 18 | } 19 | public function test_should_add_editor_params() { 20 | global $post; 21 | $repo = $this->fm->create( Repo::class ); 22 | $post = $repo->get_underlying_wp_object(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited 23 | $params = $this->editor->apply_editor( [] ); 24 | 25 | $this->assertSame( $params['editor'], [ 26 | 'description' => $repo->description, 27 | 'status' => $repo->status, 28 | 'password' => $repo->password, 29 | 'gist_id' => $repo->gist_id, 30 | 'sync' => $repo->sync, 31 | 'instances' => [], 32 | 'width' => '2', 33 | 'theme' => 'default', 34 | 'invisibles' => 'off', 35 | 'tabs' => 'off', 36 | 'errors' => [], 37 | ] ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /resources/samples/matlab: -------------------------------------------------------------------------------- 1 | n = 20; % number of points 2 | points = [random('unid', 100, n, 1), random('unid', 100, n, 1)]; 3 | len = zeros(1, n - 1); 4 | points = sortrows(points); 5 | %% Initial set of points 6 | plot(points(:,1),points(:,2)); 7 | for i = 1: n-1 8 | len(i) = points(i + 1, 1) - points(i, 1); 9 | end 10 | while(max(len) > 2 * min(len)) 11 | [d, i] = max(len); 12 | k = on_margin(points, i, d, -1); 13 | m = on_margin(points, i + 1, d, 1); 14 | xm = 0; ym = 0; 15 | %% New point 16 | if(i == 1 || i + 1 == n) 17 | xm = mean(points([i,i+1],1)) 18 | ym = mean(points([i,i+1],2)) 19 | else 20 | [xm, ym] = dlg1(points([k, i, i + 1, m], 1), ... 21 | points([k, i, i + 1, m], 2)) 22 | end 23 | 24 | points = [ points(1:i, :); [xm, ym]; points(i + 1:end, :)]; 25 | end 26 | 27 | function [net] = get_fit_network(inputs, targets) 28 | % Create Network 29 | numHiddenNeurons = 20; % Adjust as desired 30 | net = newfit(inputs,targets,numHiddenNeurons); 31 | net.trainParam.goal = 0.01; 32 | net.trainParam.epochs = 1000; 33 | % Train and Apply Network 34 | [net,tr] = train(net,inputs,targets); 35 | end 36 | 37 | foo_matrix = [1, 2, 3; 4, 5, 6]'''; 38 | foo_cell = {1, 2, 3; 4, 5, 6}''.'.'; 39 | -------------------------------------------------------------------------------- /test/Integration/Console/Repo/GetTest.php: -------------------------------------------------------------------------------- 1 | cli->shouldReceive( 'line' ); 11 | $repo = $this->fm->create( Repo::class ); 12 | 13 | $result = $this->command->get( [ $repo->ID ], [] ); 14 | 15 | $this->assertTrue( $result ); 16 | } 17 | 18 | public function test_should_use_fields_array() { 19 | $this->cli->shouldReceive( 'line' ); 20 | $repo = $this->fm->create( Repo::class ); 21 | 22 | $result = $this->command->get( [ $repo->ID ], [ 23 | 'fields' => [ 'description', 'slug' ], 24 | ] ); 25 | 26 | $this->assertTrue( $result ); 27 | } 28 | 29 | public function test_should_use_fields_string() { 30 | $this->cli->shouldReceive( 'line' ); 31 | $repo = $this->fm->create( Repo::class ); 32 | 33 | $result = $this->command->get( [ $repo->ID ], [ 34 | 'fields' => 'description,slug', 35 | ] ); 36 | 37 | $this->assertTrue( $result ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /client/components/EditPage/Description.scss: -------------------------------------------------------------------------------- 1 | @import "./common"; 2 | 3 | .wpgp-editor-header-container { 4 | display: table; 5 | width: 100%; 6 | } 7 | 8 | .wpgp-editor-header-row { 9 | display: table-row; 10 | } 11 | 12 | .wpgp-editor-description-container { 13 | display: table-cell; 14 | } 15 | 16 | .wpgp-editor-loader-container { 17 | display: table-cell; 18 | width: 1px; 19 | height: 1px; 20 | white-space: nowrap; 21 | vertical-align: middle; 22 | padding: 0 10px; 23 | margin: 0; 24 | } 25 | 26 | .wpgp-editor-options-button { 27 | font-size: 2.7em; 28 | line-height: 100%; 29 | width: 1em; 30 | color: black; 31 | position: relative; 32 | background-color: white; 33 | box-sizing: border-box; 34 | box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); 35 | cursor: pointer; 36 | outline: none; 37 | 38 | &:focus { 39 | border: 1px solid $light-blue; 40 | box-shadow: 0 0 2px $dark-blue; 41 | } 42 | 43 | &::before { 44 | position: absolute; 45 | margin: 3px auto; 46 | width: 1em; 47 | height: 1em; 48 | font-size: 0.92em; 49 | left: -1px; 50 | right: 0; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /client/components/SettingsPage/Jobs/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { i18n } from '../../../helpers'; 3 | import Row from './Row'; 4 | import { Job } from './types'; 5 | 6 | type Props = { 7 | jobs: Job[]; 8 | }; 9 | 10 | const Jobs: React.FC = ({ jobs }) => ( 11 |
12 |

{i18n('jobs.title')}

13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | {jobs.map(job => ( 34 | 35 | ))} 36 | 37 |
{i18n('jobs.name')}{i18n('jobs.description')}{i18n('jobs.status')}{i18n('jobs.runs')}{i18n('jobs.dispatch')}
{i18n('jobs.name')}{i18n('jobs.description')}{i18n('jobs.status')}{i18n('jobs.runs')}{i18n('jobs.dispatch')}
38 |
39 | ); 40 | 41 | export default Jobs; 42 | -------------------------------------------------------------------------------- /app/Http/StateController.php: -------------------------------------------------------------------------------- 1 | em = $em; 30 | } 31 | 32 | /** 33 | * Retrieves a collection of States based on the provided params. 34 | * 35 | * @param WP_REST_Request $request 36 | * 37 | * @return WP_REST_Response|WP_Error 38 | */ 39 | public function index( WP_REST_Request $request ) { 40 | $commit = $this->em->find( Commit::class, $request->get_param( 'commit_id' ), array( 41 | 'with' => 'states', 42 | ) ); 43 | 44 | if ( is_wp_error( $commit ) ) { 45 | $commit->add_data( array( 'status' => 500 ) ); 46 | 47 | return $commit; 48 | } 49 | 50 | return new WP_REST_Response( $commit->states->serialize(), 200 ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /resources/samples/php: -------------------------------------------------------------------------------- 1 | require_once 'Zend/Uri/Http.php'; 2 | 3 | namespace Location\Web; 4 | 5 | interface Factory 6 | { 7 | static function _factory(); 8 | } 9 | 10 | abstract class URI extends BaseURI implements Factory 11 | { 12 | abstract function test(); 13 | 14 | public static $st1 = 1; 15 | const ME = "Yo"; 16 | var $list = NULL; 17 | private $var; 18 | 19 | /** 20 | * Returns a URI 21 | * 22 | * @return URI 23 | */ 24 | static public function _factory($stats = array(), $uri = 'http') 25 | { 26 | echo __METHOD__; 27 | $uri = explode(':', $uri, 0b10); 28 | $schemeSpecific = isset($uri[1]) ? $uri[1] : ''; 29 | $desc = 'Multi 30 | line description'; 31 | 32 | // Security check 33 | if (!ctype_alnum($scheme)) { 34 | throw new Zend_Uri_Exception('Illegal scheme'); 35 | } 36 | 37 | $this->var = 0 - self::$st; 38 | $this->list = list(Array("1"=> 2, 2=>self::ME)); 39 | 40 | return [ 41 | 'uri' => $uri, 42 | 'value' => null, 43 | ]; 44 | } 45 | } 46 | 47 | echo URI::ME . URI::$st1; 48 | 49 | __halt_compiler () ; datahere 50 | datahere 51 | datahere */ 52 | datahere 53 | -------------------------------------------------------------------------------- /app/Model/Message.php: -------------------------------------------------------------------------------- 1 | 'json' ]; 13 | 14 | public function test_should_patch_subkey_dot_separated() { 15 | $user = $this->factory->user->create_and_get(); 16 | $args = [ 'editor.invisibles_enabled', 'on' ]; 17 | $this->cli->shouldReceive( 'get_value_from_arg_or_stdin' ) 18 | ->once() 19 | ->withArgs( [ $args, 1 ] ) 20 | ->andReturn( $args[1] ); 21 | $this->cli->shouldReceive( 'read_value' ) 22 | ->once() 23 | ->withArgs( [ $args[1], [] ] ) 24 | ->andReturn( $args[1] ); 25 | $this->cli->shouldReceive( 'success' ) 26 | ->once() 27 | ->withArgs( [ 'Updated user options.' ] ); 28 | 29 | $this->command->patch( array_merge( [ $user->ID ], $args ), [] ); 30 | 31 | $this->assertSame( $this->options->all( $user->ID ), [ 32 | 'editor' => [ 33 | 'theme' => 'default', 34 | 'invisibles_enabled' => 'on', 35 | 'tabs_enabled' => 'off', 36 | 'indent_width' => '2', 37 | ], 38 | ] ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /resources/samples/abap: -------------------------------------------------------------------------------- 1 | * Line Comments 2 | " End of line comment used as line comment. 3 | value = 1. " End of line comment 4 | 5 | DATA: 6 | "! ABAPDoc comment 7 | value TYPE i. 8 | 9 | my_string = 'Simple string'. 10 | my_string = 'String with an escaped '' inside'. 11 | my_string = |A string template: { nvalue } times|. 12 | my_string = |A string template: { nvalue } times|. 13 | my_string = |Characters \|, \{, and \} have to be escaped by \\ in literal text.|. 14 | 15 | value = 001 + 2 - 3 * 4 / 5 ** 6. 16 | 17 | IF value < 1 OR 18 | value = 2 OR 19 | value > 3 OR 20 | value <> 4 OR 21 | value <= 5 OR 22 | value >= 6. 23 | ENDIF. 24 | 25 | " Dynamic object assignment (with type cast check) 26 | lo_interface ?= lo_class. 27 | 28 | DATA: 29 | BEGIN OF my_structure, 30 | scomponent TYPE i, 31 | END OF my_structure. 32 | 33 | CLASS lcl_my_class DEFINITION. 34 | PUBLIC SECTION. 35 | METHODS my_method 36 | RETURNING 37 | VALUE(ret_value) TYPE i. 38 | ENDCLASS. 39 | 40 | CLASS lcl_my_class IMPLEMENTATION. 41 | METHOD my_method. 42 | ret_value = 1. 43 | ENDMETHOD 44 | ENDCLASS. 45 | 46 | DATA lo_instace TYPE REF TO lcl_my_class. 47 | 48 | CREATE OBJECT lo_instace. 49 | 50 | my_structure-component = lo_instace->my_method( ). 51 | -------------------------------------------------------------------------------- /client/components/Editor/util.ts: -------------------------------------------------------------------------------- 1 | import { Props } from './types'; 2 | 3 | export function editorOptionsIsEqual( 4 | prev: Pick, 5 | next: Pick, 6 | ): boolean { 7 | return prev.theme === next.theme && prev.invisibles === next.invisibles; 8 | } 9 | 10 | export function lineNumberIsEqual(/* prev, next */): boolean { 11 | // @todo implement with line numbers. 12 | return true; 13 | } 14 | 15 | export function languageIsEqual( 16 | prev: Pick, 17 | next: Pick, 18 | ): boolean { 19 | return prev.language === next.language; 20 | } 21 | 22 | export function isSpecialEvent( 23 | evt: KeyboardEvent | React.KeyboardEvent, 24 | ): boolean { 25 | const { altKey, metaKey, ctrlKey } = evt; 26 | const cmdOrCtrl = metaKey || ctrlKey; 27 | 28 | switch (evt.keyCode) { 29 | case 9: // Tab 30 | if (!cmdOrCtrl && !altKey) { 31 | return true; 32 | } 33 | break; 34 | case 13: 35 | return true; 36 | case 90: 37 | if (cmdOrCtrl) { 38 | return true; 39 | } 40 | break; 41 | case 191: 42 | if (cmdOrCtrl && !altKey) { 43 | return true; 44 | } 45 | break; 46 | } 47 | 48 | return false; 49 | } 50 | -------------------------------------------------------------------------------- /client/block/__tests__/block.spec.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | import { render, RenderResult } from '@testing-library/react'; 3 | import { createRender } from 'react-testing-kit'; 4 | import { Block } from '../Block'; 5 | 6 | const renderBlock = createRender({ 7 | defaultProps: { 8 | className: '', 9 | setAttributes: jest.fn(), 10 | blobId: null, 11 | repoId: null, 12 | }, 13 | component: Block, 14 | render, 15 | elements: ({ getByTestId }: RenderResult) => ({ 16 | setEmbed: () => getByTestId('set-embed'), 17 | editEmbed: () => getByTestId('edit-embed'), 18 | }), 19 | fire: () => ({}), 20 | waitFor: () => ({}), 21 | }); 22 | 23 | describe('Block', () => { 24 | it('should render setEmbed with no values', () => { 25 | const { elements } = renderBlock(); 26 | 27 | expect(elements.setEmbed()).toBeInTheDocument(); 28 | }); 29 | 30 | it('should render setEmbed with only blobId', () => { 31 | const { elements } = renderBlock({ blobId: 123 }); 32 | 33 | expect(elements.setEmbed()).toBeInTheDocument(); 34 | }); 35 | 36 | it('should render edit embed with both repoId & blobId', () => { 37 | const { elements } = renderBlock({ repoId: 123, blobId: 456 }); 38 | 39 | expect(elements.editEmbed()).toBeInTheDocument(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /e2e/content.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | import languages from '../resources/languages.json'; 3 | import { createGistpen } from './helpers'; 4 | 5 | describe('content', () => { 6 | for (let [slug, displayName] of Object.entries(languages.list)) { 7 | if (process.env.SKIP_IMAGE_TESTS === 'true' && slug !== 'js') { 8 | continue; 9 | } 10 | 11 | const localPath = require('path').join( 12 | __dirname, 13 | '..', 14 | 'resources', 15 | 'samples', 16 | slug, 17 | ); 18 | 19 | if (!require('fs').existsSync(localPath)) { 20 | it.todo(`should display ${displayName}`); 21 | continue; 22 | } 23 | 24 | it(`should display ${displayName} (${slug})`, async () => { 25 | let { repoUrl } = await createGistpen({ 26 | description: `Test ${displayName}`, 27 | filename: `test.${slug}`, 28 | slug, 29 | }); 30 | 31 | await page.goto(repoUrl); 32 | 33 | if ((languages.aliases as any)[slug]) { 34 | slug = (languages.aliases as any)[slug]; 35 | } 36 | 37 | const element = await page.waitForSelector(`.gistpen.language-${slug}`); 38 | const screenshot = await element.screenshot(); 39 | 40 | expect(screenshot).toMatchImageSnapshot(); 41 | }); 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /resources/samples/erlang: -------------------------------------------------------------------------------- 1 | -module(ssh_cli). 2 | 3 | -behaviour(ssh_channel). 4 | 5 | -include("ssh.hrl"). 6 | %% backwards compatibility 7 | -export([listen/1, listen/2, listen/3, listen/4, stop/1]). 8 | 9 | if L =/= [] -> % If L is not empty 10 | sum(L) / count(L); 11 | true -> 12 | error 13 | end. 14 | 15 | %% state 16 | -record(state, { 17 | cm, 18 | channel 19 | }). 20 | 21 | -spec foo(integer()) -> integer(). 22 | foo(X) -> 1 + X. 23 | 24 | test(Foo)->Foo. 25 | 26 | init([Shell, Exec]) -> 27 | {ok, #state{shell = Shell, exec = Exec}}; 28 | init([Shell]) -> 29 | false = not true, 30 | io:format("Hello, \"~p!~n", [atom_to_list('World')]), 31 | {ok, #state{shell = Shell}}. 32 | 33 | concat([Single]) -> Single; 34 | concat(RList) -> 35 | EpsilonFree = lists:filter( 36 | fun (Element) -> 37 | case Element of 38 | epsilon -> false; 39 | _ -> true 40 | end 41 | end, 42 | RList), 43 | case EpsilonFree of 44 | [Single] -> Single; 45 | Other -> {concat, Other} 46 | end. 47 | 48 | union_dot_union({union, _}=U1, {union, _}=U2) -> 49 | union(lists:flatten( 50 | lists:map( 51 | fun (X1) -> 52 | lists:map( 53 | fun (X2) -> 54 | concat([X1, X2]) 55 | end, 56 | union_to_list(U2) 57 | ) 58 | end, 59 | union_to_list(U1) 60 | ))). 61 | -------------------------------------------------------------------------------- /client/components/Loader/Loader.scss: -------------------------------------------------------------------------------- 1 | .loader, 2 | .loader::after, 3 | .mce-container .loader, 4 | .mce-container .loader::after { 5 | border-radius: 50%; 6 | width: 1.5em; 7 | height: 1.5em; 8 | } 9 | 10 | .loader, 11 | .mce-container .loader { 12 | margin-left: 1em; 13 | font-size: 10px; 14 | position: relative; 15 | text-indent: -9999em; 16 | border-top: 0.25em solid rgba(0, 0, 0, 0.2); 17 | border-right: 0.25em solid rgba(0, 0, 0, 0.2); 18 | border-bottom: 0.25em solid rgba(0, 0, 0, 0.2); 19 | border-left: 0.25em solid #000; 20 | -webkit-transform: translateZ(0); 21 | -ms-transform: translateZ(0); 22 | transform: translateZ(0); 23 | -webkit-animation: load8 1.1s infinite linear; 24 | animation: load8 1.1s infinite linear; 25 | } 26 | 27 | @-webkit-keyframes load8 { 28 | 0% { 29 | -webkit-transform: rotate(0deg); 30 | transform: rotate(0deg); 31 | } 32 | 33 | 100% { 34 | -webkit-transform: rotate(360deg); 35 | transform: rotate(360deg); 36 | } 37 | } 38 | 39 | @keyframes load8 { 40 | 0% { 41 | -webkit-transform: rotate(0deg); 42 | transform: rotate(0deg); 43 | } 44 | 45 | 100% { 46 | -webkit-transform: rotate(360deg); 47 | transform: rotate(360deg); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/Integration/Http/Site/ResourceTest.php: -------------------------------------------------------------------------------- 1 | set_role( 'subscriber' ); 11 | $request = new WP_REST_Request( 'GET', '/intraxia/v1/gistpen/site' ); 12 | 13 | $response = $this->server->dispatch( $request ); 14 | 15 | $this->assertResponseStatus( $response, 401 ); 16 | $this->assertResponseData( $response, [ 17 | 'code' => 'unauthorized', 18 | 'message' => 'Unauthorized user', 19 | 'data' => [ 20 | 'status' => 401, 21 | ], 22 | ] ); 23 | } 24 | 25 | public function test_returns_site_options() { 26 | $this->set_role( 'administrator' ); 27 | $request = new WP_REST_Request( 'GET', '/intraxia/v1/gistpen/site' ); 28 | 29 | $response = $this->server->dispatch( $request ); 30 | 31 | $this->assertResponseStatus( $response, 200 ); 32 | $this->assertResponseData( $response, [ 33 | 'prism' => [ 34 | 'theme' => 'default', 35 | 'line-numbers' => false, 36 | 'show-invisibles' => false, 37 | ], 38 | 'gist' => [ 39 | 'token' => '', 40 | ], 41 | ] ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Http/CommitController.php: -------------------------------------------------------------------------------- 1 | em = $em; 29 | } 30 | 31 | /** 32 | * Retrieves a collection of Commits based on the provided params. 33 | * 34 | * @param WP_REST_Request $request 35 | * 36 | * @return WP_REST_Response|WP_Error 37 | */ 38 | public function index( WP_REST_Request $request ) { 39 | $collection = $this->em->find_by( \Intraxia\Gistpen\Model\Commit::class, array( 40 | 'repo_id' => $request->get_param( 'repo_id' ), 41 | 'with' => array( 42 | 'states' => array( 43 | 'with' => 'language', 44 | ), 45 | ), 46 | ) ); 47 | 48 | if ( is_wp_error( $collection ) ) { 49 | $collection->add_data( array( 'status' => 500 ) ); 50 | 51 | return $collection; 52 | } 53 | 54 | return new WP_REST_Response( $collection->serialize(), 200 ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /client/deltas/__tests__/routerDelta.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | import { routerDelta } from '../routerDelta'; 3 | import { routeChange } from '../../actions'; 4 | 5 | const createLocation = (search: string) => { 6 | const location = {} as any; 7 | const parser = document.createElement('a'); 8 | parser.href = `http://test.dev/editor?${search}`; 9 | ([ 10 | 'href', 11 | 'protocol', 12 | 'host', 13 | 'hostname', 14 | 'origin', 15 | 'port', 16 | 'pathname', 17 | 'search', 18 | 'hash', 19 | ] as const).forEach(prop => { 20 | location[prop] = parser[prop]; 21 | }); 22 | 23 | return location as Location; 24 | }; 25 | 26 | const createHistory = () => { 27 | const history = {} as any; 28 | 29 | // @TODO(mAAdhaTTah) fill out methods 30 | 31 | return history as History; 32 | }; 33 | 34 | describe('routerDelta', () => { 35 | const router = (route: string) => routeChange(route); 36 | 37 | it('should emit the initial route', () => { 38 | const location = createLocation('wpgp=start'); 39 | const history = createHistory(); 40 | expect( 41 | routerDelta({ router, param: 'wpgp', location, history }), 42 | ).toEmitFromDelta( 43 | [[0, KTU.value(routeChange('/start'))]], 44 | (_send, tick) => { 45 | tick(10); 46 | }, 47 | ); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /test/Integration/TestCase.php: -------------------------------------------------------------------------------- 1 | server = $wp_rest_server = new WP_REST_Server(); 20 | do_action( 'plugins_loaded' ); 21 | do_action( 'rest_api_init' ); 22 | 23 | $this->set_permalink_structure( '/%postname%/' ); 24 | } 25 | 26 | public function tearDown() { 27 | parent::tearDown(); 28 | 29 | global $wp_rest_server; 30 | $wp_rest_server = null; 31 | } 32 | 33 | protected function assertResponseStatus( WP_REST_Response $response, $status ) { 34 | $this->assertSame( $status, $response->get_status() ); 35 | } 36 | 37 | protected function assertResponseData( WP_REST_Response $response, $data ) { 38 | $this->assertSame( $data, $response->get_data() ); 39 | } 40 | 41 | protected function assertResponseHeader( WP_REST_Response $response, $header, $value ) { 42 | $headers = $response->get_headers(); 43 | 44 | $this->assertSame( isset( $headers[ $header ] ) ? $headers[ $header ] : null, $value ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /client/globals/state.ts: -------------------------------------------------------------------------------- 1 | import { getType } from 'typesafe-actions'; 2 | import { EddyReducer } from 'brookjs'; 3 | import { RootAction } from '../RootAction'; 4 | import { init } from '../actions'; 5 | import { globalsChanged } from './actions'; 6 | 7 | export type GlobalsState = { 8 | languages: { [key: string]: string }; 9 | root: string; 10 | nonce: string; 11 | url: string; 12 | ace_widths: Array; 13 | statuses: { [key: string]: string }; 14 | themes: { [key: string]: string }; 15 | demo: { 16 | filename: string; 17 | language: string; 18 | code: string; 19 | }; 20 | }; 21 | 22 | export const defaultGlobals: GlobalsState = { 23 | languages: {}, 24 | root: '', 25 | nonce: '', 26 | url: '', 27 | ace_widths: [], 28 | statuses: {}, 29 | themes: {}, 30 | demo: { 31 | filename: '', 32 | language: '', 33 | code: '', 34 | }, 35 | }; 36 | 37 | export const globalsReducer: EddyReducer = ( 38 | state = defaultGlobals, 39 | action, 40 | ) => { 41 | switch (action.type) { 42 | case getType(init): 43 | return { 44 | ...state, 45 | ...action.payload.globals, 46 | }; 47 | case getType(globalsChanged): 48 | return { 49 | ...state, 50 | ...action.payload, 51 | }; 52 | default: 53 | return state; 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /test/Unit/View/TranslationsTest.php: -------------------------------------------------------------------------------- 1 | translations = $this->app->make( Translations::class ); 15 | } 16 | 17 | public function test_translate_returns_translation_correct_key() { 18 | $theme = $this->translations->translate( 'editor.theme' ); 19 | 20 | $this->assertSame( 'Theme', $theme ); 21 | } 22 | 23 | public function test_translate_returns_not_found_incorrect_key() { 24 | $result = $this->translations->translate( 'what.is.this' ); 25 | 26 | $this->assertSame( 'Translation for key what.is.this not found.', $result ); 27 | } 28 | 29 | public function test_serializes() { 30 | $this->assertArrayHasKey( 'i18n.notfound', $this->translations->serialize() ); 31 | } 32 | 33 | public function test_translation_output() { 34 | \ob_start(); 35 | $this->translations->output_translations(); 36 | $output = \ob_get_clean(); 37 | 38 | $this->assertRegexp( '/