├── app
├── .gitkeep
└── initializers
│ └── showdown-extension.js
├── addon
├── .gitkeep
├── styles
│ └── addon.css
└── initializers
│ └── showdown-extension.js
├── tests
├── unit
│ └── .gitkeep
├── integration
│ └── .gitkeep
├── dummy
│ ├── app
│ │ ├── helpers
│ │ │ └── .gitkeep
│ │ ├── models
│ │ │ └── .gitkeep
│ │ ├── routes
│ │ │ ├── .gitkeep
│ │ │ └── application.js
│ │ ├── components
│ │ │ └── .gitkeep
│ │ ├── controllers
│ │ │ └── .gitkeep
│ │ ├── templates
│ │ │ └── application.hbs
│ │ ├── styles
│ │ │ └── app.css
│ │ ├── router.js
│ │ ├── app.js
│ │ └── index.html
│ ├── public
│ │ ├── robots.txt
│ │ └── example.md
│ └── config
│ │ ├── optional-features.json
│ │ ├── targets.js
│ │ ├── ember-cli-update.json
│ │ ├── environment.js
│ │ └── ember-try.js
├── test-helper.js
├── index.html
├── acceptance
│ └── basic-test.js
└── helpers
│ └── index.js
├── .watchmanconfig
├── .template-lintrc.js
├── .stylelintrc.js
├── .stylelintignore
├── .eslintignore
├── .prettierignore
├── .prettierrc.js
├── .editorconfig
├── .gitignore
├── public
└── images
│ ├── ribbon-html.svg
│ ├── ribbon-ts.svg
│ ├── ribbon-pink.svg
│ ├── ribbon-purple.svg
│ ├── ribbon-js.svg
│ └── ribbon-hbs.svg
├── changelog.template
├── .ember-cli
├── .npmignore
├── testem.js
├── CONTRIBUTING.md
├── ember-cli-build.js
├── LICENSE.md
├── index.js
├── .eslintrc.js
├── .github
└── workflows
│ └── ci.yml
├── RELEASE.md
├── README.md
├── CHANGELOG.md
└── package.json
/app/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addon/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/integration/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["dist"]
3 | }
4 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/.template-lintrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | extends: 'recommended',
5 | };
6 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 |
Ember Showdown Prism
2 |
3 |
--------------------------------------------------------------------------------
/.stylelintrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | extends: ['stylelint-config-standard', 'stylelint-prettier/recommended'],
5 | };
6 |
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
1 | /* Ember supports plain CSS out of the box. More info: https://cli.emberjs.com/release/advanced-use/stylesheets/ */
2 |
--------------------------------------------------------------------------------
/.stylelintignore:
--------------------------------------------------------------------------------
1 | # unconventional files
2 | /blueprints/*/files/
3 |
4 | # compiled output
5 | /dist/
6 |
7 | # addons
8 | /.node_modules.ember-try/
9 |
--------------------------------------------------------------------------------
/app/initializers/showdown-extension.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable prettier/prettier */
2 | export { default, initialize } from 'ember-showdown-prism/initializers/showdown-extension';
3 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # unconventional js
2 | /blueprints/*/files/
3 |
4 | # compiled output
5 | /dist/
6 |
7 | # misc
8 | /coverage/
9 | !.*
10 | .*/
11 |
12 | # ember-try
13 | /.node_modules.ember-try/
14 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # unconventional js
2 | /blueprints/*/files/
3 |
4 | # compiled output
5 | /dist/
6 |
7 | # misc
8 | /coverage/
9 | !.*
10 | .*/
11 |
12 | # ember-try
13 | /.node_modules.ember-try/
14 |
--------------------------------------------------------------------------------
/tests/dummy/config/optional-features.json:
--------------------------------------------------------------------------------
1 | {
2 | "application-template-wrapper": false,
3 | "default-async-observers": true,
4 | "jquery-integration": false,
5 | "template-only-glimmer-components": true
6 | }
7 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | overrides: [
5 | {
6 | files: '*.{js,ts}',
7 | options: {
8 | singleQuote: true,
9 | },
10 | },
11 | ],
12 | };
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/application.js:
--------------------------------------------------------------------------------
1 | import Route from '@ember/routing/route';
2 | import fetch from 'fetch';
3 |
4 | export default class ApplicationRoute extends Route {
5 | async model() {
6 | const result = await fetch('/example.md');
7 | return result.text();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import EmberRouter from '@ember/routing/router';
2 | import config from 'dummy/config/environment';
3 |
4 | export default class Router extends EmberRouter {
5 | location = config.locationType;
6 | rootURL = config.rootURL;
7 | }
8 |
9 | Router.map(function () {});
10 |
--------------------------------------------------------------------------------
/tests/dummy/config/targets.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable prettier/prettier */
2 | 'use strict';
3 |
4 | const browsers = [
5 | 'last 1 Chrome versions',
6 | 'last 1 Firefox versions',
7 | 'last 1 Safari versions',
8 | ];
9 |
10 | module.exports = {
11 | browsers,
12 | node: 'current'
13 | };
14 |
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import Application from 'dummy/app';
2 | import config from 'dummy/config/environment';
3 | import * as QUnit from 'qunit';
4 | import { setApplication } from '@ember/test-helpers';
5 | import { setup } from 'qunit-dom';
6 | import { start } from 'ember-qunit';
7 |
8 | setApplication(Application.create(config.APP));
9 |
10 | setup(QUnit.assert);
11 |
12 | start();
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/app.js:
--------------------------------------------------------------------------------
1 | import Application from '@ember/application';
2 | import Resolver from 'ember-resolver';
3 | import loadInitializers from 'ember-load-initializers';
4 | import config from 'dummy/config/environment';
5 |
6 | export default class App extends Application {
7 | modulePrefix = config.modulePrefix;
8 | podModulePrefix = config.podModulePrefix;
9 | Resolver = Resolver;
10 | }
11 |
12 | loadInitializers(App, config.modulePrefix);
13 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | end_of_line = lf
9 | charset = utf-8
10 | trim_trailing_whitespace = true
11 | insert_final_newline = true
12 | indent_style = space
13 | indent_size = 2
14 |
15 | [*.hbs]
16 | insert_final_newline = false
17 |
18 | [*.{diff,md}]
19 | trim_trailing_whitespace = false
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist/
3 |
4 | # dependencies
5 | /node_modules/
6 |
7 | # misc
8 | /.env*
9 | /.pnp*
10 | /.eslintcache
11 | /coverage/
12 | /npm-debug.log*
13 | /testem.log
14 | /yarn-error.log
15 |
16 | # auto-changelog
17 | /.changelog/
18 |
19 | # ember-try
20 | /.node_modules.ember-try/
21 | /npm-shrinkwrap.json.ember-try
22 | /package.json.ember-try
23 | /package-lock.json.ember-try
24 | /yarn.lock.ember-try
25 |
26 | # broccoli-debug
27 | /DEBUG/
28 |
--------------------------------------------------------------------------------
/public/images/ribbon-html.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/changelog.template:
--------------------------------------------------------------------------------
1 | {{#each releases}}
2 | x.x.x / {{isoDate}}
3 | ==================
4 | {{#if merges}}
5 | {{#each merges}}
6 | * {{#if commit.breaking}}**Breaking change:** {{/if}}{{message}} #{{id}} from @{{githubIssue.user.login}}
7 | {{/each}}
8 | {{/if}}
9 |
10 | {{#if fixes}}
11 | {{#each fixes}}
12 | * FIX: {{#if commit.breaking}}**Breaking change:** {{/if}}{{commit.subject}}{{#each fixes}} {{#if href}}[`#{{id}}`]({{href}}){{/if}}{{/each}}
13 | {{/each}}
14 | {{/if}}
15 | {{/each}}
--------------------------------------------------------------------------------
/tests/dummy/config/ember-cli-update.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": "1.0.0",
3 | "packages": [
4 | {
5 | "name": "ember-cli",
6 | "version": "5.0.0",
7 | "blueprints": [
8 | {
9 | "name": "addon",
10 | "outputRepo": "https://github.com/ember-cli/ember-addon-output",
11 | "codemodsSource": "ember-addon-codemods-manifest@1",
12 | "isBaseBlueprint": true,
13 | "options": [
14 | "--no-welcome"
15 | ]
16 | }
17 | ]
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/.ember-cli:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | Ember CLI sends analytics information by default. The data is completely
4 | anonymous, but there are times when you might want to disable this behavior.
5 |
6 | Setting `disableAnalytics` to true will prevent any data from being sent.
7 | */
8 | "disableAnalytics": false,
9 |
10 | /**
11 | Setting `isTypeScriptProject` to true will force the blueprint generators to generate TypeScript
12 | rather than JavaScript by default, when a TypeScript version of a given blueprint is available.
13 | */
14 | "isTypeScriptProject": false
15 | }
16 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist/
3 | /tmp/
4 |
5 | # misc
6 | /.editorconfig
7 | /.ember-cli
8 | /.env*
9 | /.eslintcache
10 | /.eslintignore
11 | /.eslintrc.js
12 | /.git/
13 | /.github/
14 | /.gitignore
15 | /.prettierignore
16 | /.prettierrc.js
17 | /.stylelintignore
18 | /.stylelintrc.js
19 | /.template-lintrc.js
20 | /.travis.yml
21 | /.watchmanconfig
22 | /CONTRIBUTING.md
23 | /ember-cli-build.js
24 | /testem.js
25 | /tests/
26 | /yarn-error.log
27 | /yarn.lock
28 | .gitkeep
29 |
30 | # ember-try
31 | /.node_modules.ember-try/
32 | /npm-shrinkwrap.json.ember-try
33 | /package.json.ember-try
34 | /package-lock.json.ember-try
35 | /yarn.lock.ember-try
36 |
--------------------------------------------------------------------------------
/testem.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | test_page: 'tests/index.html?hidepassed',
5 | disable_watching: true,
6 | launch_in_ci: ['Chrome'],
7 | launch_in_dev: ['Chrome'],
8 | browser_start_timeout: 120,
9 | browser_args: {
10 | Chrome: {
11 | ci: [
12 | // --no-sandbox is needed when running Chrome inside a container
13 | process.env.CI ? '--no-sandbox' : null,
14 | '--headless',
15 | '--disable-dev-shm-usage',
16 | '--disable-software-rasterizer',
17 | '--mute-audio',
18 | '--remote-debugging-port=0',
19 | '--window-size=1440,900',
20 | ].filter(Boolean),
21 | },
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/tests/dummy/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Dummy
6 |
7 |
8 |
9 | {{content-for "head"}}
10 |
11 |
12 |
13 |
14 | {{content-for "head-footer"}}
15 |
16 |
17 | {{content-for "body"}}
18 |
19 |
20 |
21 |
22 | {{content-for "body-footer"}}
23 |
24 |
25 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How To Contribute
2 |
3 | ## Installation
4 |
5 | * `git clone `
6 | * `cd ember-showdown-prism`
7 | * `npm install`
8 |
9 | ## Linting
10 |
11 | * `npm run lint`
12 | * `npm run lint:fix`
13 |
14 | ## Running tests
15 |
16 | * `ember test` – Runs the test suite on the current Ember version
17 | * `ember test --server` – Runs the test suite in "watch mode"
18 | * `ember try:each` – Runs the test suite against multiple Ember versions
19 |
20 | ## Running the dummy application
21 |
22 | * `ember serve`
23 | * Visit the dummy application at [http://localhost:4200](http://localhost:4200).
24 |
25 | For more information on using ember-cli, visit [https://cli.emberjs.com/release/](https://cli.emberjs.com/release/).
26 |
--------------------------------------------------------------------------------
/ember-cli-build.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable prettier/prettier */
2 | 'use strict';
3 |
4 | const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
5 |
6 | module.exports = function (defaults) {
7 | const app = new EmberAddon(defaults, {
8 | prember: {
9 | urls: [
10 | '/'
11 | ]
12 | }
13 | });
14 |
15 | /*
16 | This build file specifies the options for the dummy test app of this
17 | addon, located in `/tests/dummy`
18 | This build file does *not* influence how the addon or the app using it
19 | behave. You most likely want to be modifying `./index.js` or app's build file
20 | */
21 |
22 | const { maybeEmbroider } = require('@embroider/test-setup');
23 | return maybeEmbroider(app, {
24 | skipBabel: [
25 | {
26 | package: 'qunit',
27 | },
28 | ],
29 | });
30 | };
31 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2020
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Dummy Tests
6 |
7 |
8 |
9 | {{content-for "head"}}
10 | {{content-for "test-head"}}
11 |
12 |
13 |
14 |
15 |
16 | {{content-for "head-footer"}}
17 | {{content-for "test-head-footer"}}
18 |
19 |
20 | {{content-for "body"}}
21 | {{content-for "test-body"}}
22 |
23 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | {{content-for "body-footer"}}
37 | {{content-for "test-body-footer"}}
38 |
39 |
40 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable prettier/prettier */
2 | 'use strict';
3 |
4 | var Funnel = require('broccoli-funnel');
5 | const { join } = require('path');
6 |
7 | module.exports = {
8 | name: require('./package').name,
9 |
10 | treeForPublic: function () {
11 | return new Funnel(join(this.root, 'public'));
12 | },
13 |
14 | included() {
15 | let app = findHost(this);
16 | if (!app.options['ember-prism']) {
17 | app.options['ember-prism'] = {
18 | theme: 'okaidia',
19 |
20 | components: [
21 | 'apacheconf',
22 | 'bash',
23 | 'css',
24 | 'http',
25 | 'javascript',
26 | 'json',
27 | 'json5',
28 | 'markup-templating',
29 | 'ruby',
30 | 'scss',
31 | 'yaml',
32 | 'typescript',
33 | 'diff',
34 | ],
35 | plugins: ['line-numbers', 'normalize-whitespace']
36 | };
37 | }
38 |
39 | this._super.included.apply(this, arguments);
40 | },
41 | };
42 |
43 | // Polyfill [Addon._findHost](https://ember-cli.com/api/classes/Addon.html#method__findHost) for older versions of ember-cli
44 | function findHost(addon) {
45 | var current = addon;
46 | var app;
47 |
48 | do {
49 | app = current.app || app;
50 | } while (current.parent.parent && (current = current.parent));
51 |
52 | return app;
53 | }
54 |
--------------------------------------------------------------------------------
/tests/acceptance/basic-test.js:
--------------------------------------------------------------------------------
1 | import { module, test } from 'qunit';
2 | import { visit, currentURL } from '@ember/test-helpers';
3 | import { setupApplicationTest } from 'ember-qunit';
4 |
5 | module('Acceptance | index', function (hooks) {
6 | setupApplicationTest(hooks);
7 |
8 | test('visiting /', async function (assert) {
9 | await visit('/');
10 |
11 | assert.strictEqual(currentURL(), '/');
12 | assert.dom('pre.language-none code.language-none').isVisible();
13 | assert
14 | .dom('pre.language-none code.language-none')
15 | .hasText('sh go do a thing');
16 |
17 | assert.dom('pre.language-javascript code.language-javascript').isVisible();
18 | assert
19 | .dom('pre.language-javascript code.language-javascript')
20 | .hasText(`let thing = 'face'; let myElement = $('.my-element');`);
21 |
22 | assert.dom('div.filename .ribbon').isVisible();
23 | assert.dom('div.filename span').hasText('app/templates/blog-post.hbs');
24 | assert.dom('pre.language-handlebars code.language-handlebars').isVisible();
25 | assert
26 | .dom('pre.language-handlebars code.language-handlebars')
27 | .containsText(
28 | `{{@model.title}}
by {{@model.author}}
{{ (count @model.posts) }} # posts
{{@model.intro}}
{{@model.body}}
`
29 | );
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | root: true,
5 | parser: '@babel/eslint-parser',
6 | parserOptions: {
7 | ecmaVersion: 'latest',
8 | sourceType: 'module',
9 | requireConfigFile: false,
10 | babelOptions: {
11 | plugins: [
12 | ['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }],
13 | ],
14 | },
15 | },
16 | plugins: ['ember'],
17 | extends: [
18 | 'eslint:recommended',
19 | 'plugin:ember/recommended',
20 | 'plugin:prettier/recommended',
21 | ],
22 | env: {
23 | browser: true,
24 | },
25 | rules: {},
26 | overrides: [
27 | // node files
28 | {
29 | files: [
30 | './.eslintrc.js',
31 | './.prettierrc.js',
32 | './.stylelintrc.js',
33 | './.template-lintrc.js',
34 | './ember-cli-build.js',
35 | './index.js',
36 | './testem.js',
37 | './blueprints/*/index.js',
38 | './config/**/*.js',
39 | './tests/dummy/config/**/*.js',
40 | ],
41 | parserOptions: {
42 | sourceType: 'script',
43 | },
44 | env: {
45 | browser: false,
46 | node: true,
47 | },
48 | extends: ['plugin:n/recommended'],
49 | },
50 | {
51 | // test files
52 | files: ['tests/**/*-test.{js,ts}'],
53 | extends: ['plugin:qunit/recommended'],
54 | },
55 | ],
56 | };
57 |
--------------------------------------------------------------------------------
/tests/helpers/index.js:
--------------------------------------------------------------------------------
1 | import {
2 | setupApplicationTest as upstreamSetupApplicationTest,
3 | setupRenderingTest as upstreamSetupRenderingTest,
4 | setupTest as upstreamSetupTest,
5 | } from 'ember-qunit';
6 |
7 | // This file exists to provide wrappers around ember-qunit's / ember-mocha's
8 | // test setup functions. This way, you can easily extend the setup that is
9 | // needed per test type.
10 |
11 | function setupApplicationTest(hooks, options) {
12 | upstreamSetupApplicationTest(hooks, options);
13 |
14 | // Additional setup for application tests can be done here.
15 | //
16 | // For example, if you need an authenticated session for each
17 | // application test, you could do:
18 | //
19 | // hooks.beforeEach(async function () {
20 | // await authenticateSession(); // ember-simple-auth
21 | // });
22 | //
23 | // This is also a good place to call test setup functions coming
24 | // from other addons:
25 | //
26 | // setupIntl(hooks); // ember-intl
27 | // setupMirage(hooks); // ember-cli-mirage
28 | }
29 |
30 | function setupRenderingTest(hooks, options) {
31 | upstreamSetupRenderingTest(hooks, options);
32 |
33 | // Additional setup for rendering tests can be done here.
34 | }
35 |
36 | function setupTest(hooks, options) {
37 | upstreamSetupTest(hooks, options);
38 |
39 | // Additional setup for unit tests can be done here.
40 | }
41 |
42 | export { setupApplicationTest, setupRenderingTest, setupTest };
43 |
--------------------------------------------------------------------------------
/public/images/ribbon-ts.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable prettier/prettier */
2 | 'use strict';
3 |
4 | module.exports = function (environment) {
5 | const ENV = {
6 | modulePrefix: 'dummy',
7 | environment,
8 | rootURL: '/',
9 | locationType: 'history',
10 | EmberENV: {
11 | EXTEND_PROTOTYPES: false,
12 | FEATURES: {
13 | // Here you can enable experimental features on an ember canary build
14 | // e.g. EMBER_NATIVE_DECORATOR_SUPPORT: true
15 | },
16 | },
17 |
18 | APP: {
19 | // Here you can pass flags/options to your application instance
20 | // when it is created
21 | },
22 | fastboot: {
23 | hostWhitelist: [/^localhost:\d+$/]
24 | }
25 | };
26 |
27 | if (environment === 'development') {
28 | // ENV.APP.LOG_RESOLVER = true;
29 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
30 | // ENV.APP.LOG_TRANSITIONS = true;
31 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
32 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
33 | }
34 |
35 | if (environment === 'test') {
36 | // Testem prefers this...
37 | ENV.locationType = 'none';
38 |
39 | // keep test console output quieter
40 | ENV.APP.LOG_ACTIVE_GENERATION = false;
41 | ENV.APP.LOG_VIEW_LOOKUPS = false;
42 |
43 | ENV.APP.rootElement = '#ember-testing';
44 | ENV.APP.autoboot = false;
45 | }
46 |
47 | if (environment === 'production') {
48 | // here you can enable a production-specific feature
49 | }
50 |
51 | return ENV;
52 | };
53 |
--------------------------------------------------------------------------------
/public/images/ribbon-pink.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/public/images/ribbon-purple.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/public/images/ribbon-js.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/images/ribbon-hbs.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - master
8 | pull_request: {}
9 |
10 | concurrency:
11 | group: ci-${{ github.head_ref || github.ref }}
12 | cancel-in-progress: true
13 |
14 | jobs:
15 | test:
16 | name: "Tests"
17 | runs-on: ubuntu-latest
18 | timeout-minutes: 10
19 |
20 | steps:
21 | - uses: actions/checkout@v3
22 | - name: Install Node
23 | uses: actions/setup-node@v3
24 | with:
25 | node-version: 16
26 | cache: npm
27 | - name: Install Dependencies
28 | run: npm ci
29 | - name: Lint
30 | run: npm run lint
31 | - name: Run Tests
32 | run: npm run test:ember
33 |
34 | floating:
35 | name: "Floating Dependencies"
36 | runs-on: ubuntu-latest
37 | timeout-minutes: 10
38 |
39 | steps:
40 | - uses: actions/checkout@v3
41 | - uses: actions/setup-node@v3
42 | with:
43 | node-version: 16
44 | cache: npm
45 | - name: Install Dependencies
46 | run: npm install --no-shrinkwrap
47 | - name: Run Tests
48 | run: npm run test:ember
49 |
50 | try-scenarios:
51 | name: ${{ matrix.try-scenario }}
52 | runs-on: ubuntu-latest
53 | needs: "test"
54 | timeout-minutes: 10
55 |
56 | strategy:
57 | fail-fast: false
58 | matrix:
59 | try-scenario:
60 | - ember-lts-3.16
61 | - ember-lts-3.20
62 | - ember-lts-3.24
63 | - ember-lts-3.28
64 | - ember-lts-4.4
65 | - ember-lts-4.8
66 | - ember-lts-4.12
67 | - ember-release
68 | - ember-beta
69 | - ember-canary
70 | - embroider-safe
71 | - embroider-optimized
72 | - ember-release-no-deprecations
73 | - no-deprecations
74 |
75 | steps:
76 | - uses: actions/checkout@v3
77 | - name: Install Node
78 | uses: actions/setup-node@v3
79 | with:
80 | node-version: 16
81 | cache: npm
82 | - name: Install Dependencies
83 | run: npm ci
84 | - name: Run Tests
85 | run: ./node_modules/.bin/ember try:one ${{ matrix.try-scenario }}
86 |
--------------------------------------------------------------------------------
/RELEASE.md:
--------------------------------------------------------------------------------
1 | # Release Process
2 |
3 | Releases are mostly automated using
4 | [release-it](https://github.com/release-it/release-it/) and
5 | [lerna-changelog](https://github.com/lerna/lerna-changelog/).
6 |
7 | ## Preparation
8 |
9 | Since the majority of the actual release process is automated, the primary
10 | remaining task prior to releasing is confirming that all pull requests that
11 | have been merged since the last release have been labeled with the appropriate
12 | `lerna-changelog` labels and the titles have been updated to ensure they
13 | represent something that would make sense to our users. Some great information
14 | on why this is important can be found at
15 | [keepachangelog.com](https://keepachangelog.com/en/1.0.0/), but the overall
16 | guiding principle here is that changelogs are for humans, not machines.
17 |
18 | When reviewing merged PR's the labels to be used are:
19 |
20 | * breaking - Used when the PR is considered a breaking change.
21 | * enhancement - Used when the PR adds a new feature or enhancement.
22 | * bug - Used when the PR fixes a bug included in a previous release.
23 | * documentation - Used when the PR adds or updates documentation.
24 | * internal - Used for internal changes that still require a mention in the
25 | changelog/release notes.
26 |
27 | ## Release
28 |
29 | Once the prep work is completed, the actual release is straight forward:
30 |
31 | * First, ensure that you have installed your projects dependencies:
32 |
33 | ```sh
34 | npm install
35 | ```
36 |
37 | * Second, ensure that you have obtained a
38 | [GitHub personal access token][generate-token] with the `repo` scope (no
39 | other permissions are needed). Make sure the token is available as the
40 | `GITHUB_AUTH` environment variable.
41 |
42 | For instance:
43 |
44 | ```bash
45 | export GITHUB_AUTH=abc123def456
46 | ```
47 |
48 | [generate-token]: https://github.com/settings/tokens/new?scopes=repo&description=GITHUB_AUTH+env+variable
49 |
50 | * And last (but not least 😁) do your release.
51 |
52 | ```sh
53 | npx release-it
54 | ```
55 |
56 | [release-it](https://github.com/release-it/release-it/) manages the actual
57 | release process. It will prompt you to to choose the version number after which
58 | you will have the chance to hand tweak the changelog to be used (for the
59 | `CHANGELOG.md` and GitHub release), then `release-it` continues on to tagging,
60 | pushing the tag and commits, etc.
61 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ember-showdown-prism
2 |
3 | ember-showdown-prism is a drop-in addon that automatically adds [Prism](https://prismjs.com/) syntax highlighting to code blocks if you are using [showdown](https://github.com/showdownjs/showdown) to render your Markdown.
4 |
5 | This addon also provides filename wrappers to the code block, with filetype icons, if a code block is marked with a `data-filename` attribute:
6 |
7 | ```markdown
8 |
9 | ````handlebars {data-filename=app/templates/blog-post.hbs}
10 | {{@model.title}}
11 | by {{@model.author}}
12 |
13 |
14 | {{@model.intro}}
15 |
16 |
17 |
18 | {{@model.body}}
19 |
20 | ```
21 | ```
22 |
23 | 
24 |
25 | You will also notice that the code sample has line numbers, this is built-in behaviour and they will be added to all code blocks. The line numbers also have anchors with ids added, which makes them clickable in Fastboot or prember environments.
26 |
27 | This is also specifically designed to work in Node environments so that it can run effectively in Fastboot and prember 🎉 and as it is a drop-in addon it will automatically start working if added to any [Empress](https://github.com/empress) projects, so it can be used to add syntax highlighting to your [empress-blog](https://github.com/empress/empress-blog) if your template doesn't already provide syntax highlighting.
28 |
29 | This addon is building on top of the great work of [ember-cli-showdown](https://github.com/gcollazo/ember-cli-showdown) and [ember-prism](https://github.com/shipshapecode/ember-prism).
30 |
31 |
32 | ## Compatibility
33 |
34 | * Ember.js v3.16 or above
35 | * Ember CLI v3.16 or above
36 | * Node.js v16 or above
37 |
38 |
39 | ## Installation
40 |
41 | ```
42 | ember install ember-showdown-prism
43 | ```
44 |
45 |
46 | ## Usage
47 |
48 | Most people don't need to do anything to configure this addon as it comes with a sensible set of default languages that it supports, but if you want to customise the languages that Prism has access to then you can follow the [ember-prism documentation on adding language](https://github.com/shipshapecode/ember-prism#configuration)
49 |
50 | Note: because of the limitations of using Prism in a Node environment you cannot use most prism plugins, essentially you cannot use anything that requires the DOM element while the plugin code is running.
51 |
52 |
53 | ## Contributing
54 |
55 | See the [Contributing](CONTRIBUTING.md) guide for details.
56 |
57 |
58 | ## License
59 |
60 | This project is licensed under the [MIT License](LICENSE.md).
61 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## v4.4.0 (2023-09-29)
4 |
5 | #### :rocket: Enhancement
6 | * [#58](https://github.com/empress/ember-showdown-prism/pull/58) add json5, line-numbers, and normalize-whitespace ([@lupestro](https://github.com/lupestro))
7 |
8 | #### Committers: 1
9 | - Ralph Mack ([@lupestro](https://github.com/lupestro))
10 |
11 | ## v4.3.0 (2023-09-29)
12 |
13 | #### :rocket: Enhancement
14 | * [#51](https://github.com/empress/ember-showdown-prism/pull/51) Use the setup function from ember-prism ([@NullVoxPopuli](https://github.com/NullVoxPopuli))
15 |
16 | #### :bug: Bug Fix
17 | * [#57](https://github.com/empress/ember-showdown-prism/pull/57) Fix data-diff first line bug ([@fry69](https://github.com/fry69))
18 |
19 | #### Committers: 2
20 | - [@NullVoxPopuli](https://github.com/NullVoxPopuli)
21 | - [@fry69](https://github.com/fry69)
22 |
23 | 4.2.0 / 2023-07-10
24 | ==================
25 |
26 | * add support for data-diff usage in code block #53 from @mansona
27 |
28 | 4.1.0 / 2023-07-03
29 | ==================
30 |
31 | * move ember-prism back to dependencies #49 from @mansona
32 |
33 | 4.0.0 / 2023-07-03
34 | ==================
35 |
36 | * update to v5.0 with ember-cli-update #47 from @mansona
37 | * move showdown to a peer dependency #45 from @mansona
38 | * breaking: drop support for node < 16 #46 from @mansona
39 |
40 | 3.2.0 / 2022-08-06
41 | ==================
42 | * update ember-prism #31 from @mansona
43 | * fix ember-try npm overrides #27 from @mansona
44 |
45 | 3.1.0 / 2022-05-05
46 | ==================
47 | * add typescript and diff components #25 from @mansona
48 |
49 | 3.0.0 / 2021-12-31
50 | ==================
51 |
52 | * update with ember-cli-update to 3.28 #20 from @mansona
53 | * add a basic test #19 from @mansona
54 | * Breaking: drop Node 10 and unify github ci workflow with blueprint #18 from @mansona
55 |
56 | 2.3.0 / 2021-08-12
57 | ==================
58 |
59 | * fix dollar signs in codeblocks breaking when running through Prism #13 from @nickschot
60 | * add a `$` to the demo app to demonstrate the issues with it #14 from @nickschot
61 | * update with ember-cli-update #16 from @mansona
62 | * Move from travis to github actions #15 from @mansona
63 | * add prember for netlify example app #10 from @mansona
64 | * add a better README #9 from @mansona
65 |
66 | 2.2.0 / 2020-08-20
67 | ==================
68 |
69 | * add linkable line numbers to highlighted code blocks #8 from @nickschot
70 |
71 | 2.1.0 / 2020-08-19
72 | ==================
73 |
74 | * add assertion if missing language is used & fallback to non-prism rendering #5 from @nickschot
75 | * add YAML to the default enabled languages #6 from @nickschot
76 |
77 | 2.0.0 / 2020-08-17
78 | ==================
79 |
80 | This is only a breaking change because it dropped support for Node 8 and Ember < 3.12. They will likely continue to work for a little while but we are no longer testing them 👍
81 |
82 | * use findHost to find the app (fixes non-working prism when using this addon indirectly) #4 from @nickschot
83 | * Breaking: Update dependencies #2 from @mansona
84 |
--------------------------------------------------------------------------------
/addon/styles/addon.css:
--------------------------------------------------------------------------------
1 | div.filename {
2 | background-color: #292929;
3 | }
4 |
5 | pre[class*="language-"] {
6 | background-color: #151515;
7 | }
8 |
9 | .filename {
10 | border-radius: 0.3em;
11 | }
12 |
13 | .ribbon {
14 | margin-top: 0.33em;
15 | float: right;
16 | height: 20px;
17 | width: 52px;
18 | background: 0 0 no-repeat;
19 | background-size: 52px 20px;
20 | }
21 |
22 | .filename > span {
23 | font-family: Menlo, "DejaVu Sans Mono", "Bitstream Vera Sans Mono", Courier,
24 | monospace;
25 | font-size: 0.8em;
26 | color: lightgrey;
27 | display: block;
28 | padding: 5px 0 0 10px;
29 | }
30 |
31 | .filename.javascript .ribbon,
32 | .filename.js .ribbon {
33 | background-image: url("/images/ribbon-js.svg");
34 | }
35 |
36 | .filename.html .ribbon {
37 | background-image: url("/images/ribbon-html.svg");
38 | }
39 |
40 | .filename.handlebars .ribbon,
41 | .filename.hbs .ribbon {
42 | background-image: url("/images/ribbon-hbs.svg");
43 | }
44 |
45 | .filename.typescript .ribbon,
46 | .filename.ts .ribbon {
47 | background-image: url("/images/ribbon-ts.svg");
48 | }
49 |
50 | code {
51 | font-feature-settings: "kern", "tnum";
52 | }
53 |
54 | pre[class*="language-"].line-numbers {
55 | position: relative;
56 | padding-left: 3.8em;
57 | counter-reset: linenumber;
58 | }
59 |
60 | pre[class*="language-"].line-numbers > code {
61 | position: relative;
62 | white-space: inherit;
63 | }
64 |
65 | .line-numbers .line-numbers-rows {
66 | position: absolute;
67 | top: 0;
68 | font-size: 100%;
69 | left: -3.8em;
70 | width: 3em; /* works for line-numbers below 1000 lines */
71 | letter-spacing: -1px;
72 | border-right: 1px solid #999;
73 | }
74 |
75 | .line-numbers-rows > a {
76 | display: block;
77 | counter-increment: linenumber;
78 | background: none !important;
79 | text-decoration: none !important;
80 | }
81 |
82 | .line-numbers-rows > a::before {
83 | content: counter(linenumber);
84 | color: #999;
85 | display: block;
86 | padding-right: 0.8em;
87 | text-align: right;
88 | }
89 |
90 | .line-numbers-rows > a:hover::before,
91 | .line-numbers-rows > a:focus::before {
92 | color: #fff;
93 | }
94 |
95 | .token.regex,
96 | .token.important,
97 | .token.variable {
98 | color: #c3f590;
99 | }
100 |
101 | code > .token.property,
102 | code > .token.tag,
103 | code > .token.constant,
104 | code > .token.symbol,
105 | code > .token.deleted {
106 | color: #ff6fa3;
107 | }
108 |
109 | code > .diff-insertion {
110 | background-color: rgb(93 125 93 / 50%);
111 |
112 | .token.property,
113 | .token.tag,
114 | .token.constant,
115 | .token.symbol,
116 | .token.deleted {
117 | color: #ff95bb;
118 | }
119 | }
120 |
121 | code > .diff-deletion {
122 | background-color: rgb(144 84 84 / 70%);
123 |
124 | .token.property,
125 | .token.tag,
126 | .token.constant,
127 | .token.symbol,
128 | .token.deleted {
129 | color: #ffaac8;
130 | }
131 | }
132 |
133 | /* don't include "removed" code when copy-pasting diffs */
134 | code .diff-operator,
135 | code .diff-deletion {
136 | user-select: none;
137 | }
138 |
139 | code .token.comment {
140 | color: #e6e6e6;
141 | }
142 |
--------------------------------------------------------------------------------
/tests/dummy/public/example.md:
--------------------------------------------------------------------------------
1 | Start with something simple
2 |
3 | This is an inline code example `sh go do a thing`.
4 |
5 | Let's make it a block
6 | ```
7 | sh go do a thing
8 | ```
9 |
10 | Adding a `javascript` as a language to get syntax highlighting
11 | ```javascript
12 | let thing = 'face';
13 | let myElement = $('.my-element');
14 | ```
15 |
16 | Now let's do something a bit more complex
17 |
18 | ```handlebars {data-filename=app/templates/blog-post.hbs}
19 | {{@model.title}}
20 | by {{@model.author}}
21 | {{ (count @model.posts) }} # posts
22 |
23 |
24 | {{@model.intro}}
25 |
26 |
27 |
28 | {{@model.body}}
29 |
30 |
31 |
48 | <:block as |foo baz|>
49 | {{foo}}
50 |
51 | {{#let foo.bar 12 as |fooBar num|}}
52 |
53 | {{/let}}
54 |
55 | {{! comment }}
56 | {{!-- block }}
57 | TODO: Indentation is broken after that
58 | comment --}}
59 |
60 |
61 |
62 |
63 | ```
64 |
65 | With some different file types
66 |
67 | ```javascript {data-filename=app/controllers/blog-post.js}
68 | import Controller from '@ember/controller';
69 | import { action } from '@ember/object';
70 |
71 | export default class BlogPostController extends Controller {
72 | isExpanded = false
73 |
74 | @action
75 | toggleBody() {
76 | this.toggleProperty('isExpanded');
77 | }
78 | }
79 | ```
80 |
81 | Typescript never hurts
82 |
83 | ```typescript {data-filename=app/router.ts}
84 | import EmberRouter from '@ember/routing/router';
85 | import config from './config/environment';
86 |
87 | export default class Router extends EmberRouter {
88 | location = config.locationType;
89 | rootURL = config.rootURL;
90 | }
91 |
92 | Router.map(function() {});
93 | ```
94 |
95 | With a diff:
96 |
97 | ```javascript {data-filename="app/router.js" data-diff="+10,-11"}
98 | import EmberRouter from '@ember/routing/router';
99 | import config from './config/environment';
100 |
101 | const Router = EmberRouter.extend({
102 | location: config.locationType,
103 | rootURL: config.rootURL
104 | });
105 |
106 | Router.map(function() {
107 | this.route('about');
108 | this.route('face');
109 | });
110 |
111 | export default Router;
112 | ```
113 |
114 | With a diff on the first line:
115 |
116 | ```javascript {data-filename="app/router.js" data-diff="-1,+2"}
117 | import EmberRouter from '@ember/routing/router';
118 | import EmberRouter from '@embroider/router';
119 | import config from './config/environment';
120 |
121 | const Router = EmberRouter.extend({
122 | location: config.locationType,
123 | rootURL: config.rootURL
124 | });
125 |
126 | Router.map(function() {
127 | this.route('about');
128 | });
129 |
130 | export default Router;
131 | ```
132 |
--------------------------------------------------------------------------------
/tests/dummy/config/ember-try.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable prettier/prettier */
2 | 'use strict';
3 |
4 | const getChannelURL = require('ember-source-channel-url');
5 | const { embroiderSafe, embroiderOptimized } = require('@embroider/test-setup');
6 |
7 | module.exports = async function () {
8 | return {
9 | scenarios: [
10 | {
11 | name: 'ember-lts-3.16',
12 | npm: {
13 | devDependencies: {
14 | 'ember-cli': '^4.0.0',
15 | 'ember-source': '~3.16.0',
16 | 'ember-qunit': '6.0.0',
17 | 'ember-resolver': '^8.0.0',
18 | '@ember/test-helpers': '^2.9.0',
19 | }
20 | }
21 | },
22 | {
23 | name: 'ember-lts-3.20',
24 | npm: {
25 | devDependencies: {
26 | 'ember-cli': '^4.0.0',
27 | 'ember-source': '~3.20.5',
28 | 'ember-qunit': '6.0.0',
29 | 'ember-resolver': '^8.0.0',
30 | '@ember/test-helpers': '^2.9.0',
31 | },
32 | },
33 | },
34 | {
35 | name: 'ember-lts-3.24',
36 | npm: {
37 | devDependencies: {
38 | 'ember-cli': '^4.0.0',
39 | 'ember-source': '~3.24.3',
40 | 'ember-qunit': '6.0.0',
41 | 'ember-resolver': '^8.0.0',
42 | '@ember/test-helpers': '^2.9.0',
43 | },
44 | },
45 | },
46 | {
47 | name: 'ember-lts-3.28',
48 | npm: {
49 | devDependencies: {
50 | 'ember-cli': '^4.0.0',
51 | 'ember-source': '~3.28.0',
52 | 'ember-qunit': '^6.2.0',
53 | 'ember-resolver': '^8.0.0',
54 | '@ember/test-helpers': '^2.9.0',
55 | },
56 | },
57 | },
58 | {
59 | name: 'ember-lts-4.4',
60 | npm: {
61 | devDependencies: {
62 | 'ember-source': '~4.4.0',
63 | 'ember-resolver': '^8.0.0',
64 | },
65 | },
66 | },
67 | {
68 | name: 'ember-lts-4.8',
69 | npm: {
70 | devDependencies: {
71 | 'ember-source': '~4.8.0',
72 | },
73 | },
74 | },
75 | {
76 | name: 'ember-lts-4.12',
77 | npm: {
78 | devDependencies: {
79 | 'ember-source': '~4.12.0',
80 | },
81 | },
82 | },
83 | {
84 | name: 'ember-release',
85 | npm: {
86 | devDependencies: {
87 | 'ember-source': await getChannelURL('release'),
88 | },
89 | overrides: {
90 | 'ember-source': '$ember-source',
91 | },
92 | },
93 | },
94 | {
95 | name: 'ember-beta',
96 | npm: {
97 | devDependencies: {
98 | 'ember-source': await getChannelURL('beta'),
99 | },
100 | overrides: {
101 | 'ember-source': '$ember-source',
102 | },
103 | },
104 | },
105 | {
106 | name: 'ember-canary',
107 | npm: {
108 | devDependencies: {
109 | 'ember-source': await getChannelURL('canary'),
110 | },
111 | overrides: {
112 | 'ember-source': '$ember-source',
113 | },
114 | },
115 | },
116 | embroiderSafe(),
117 | embroiderOptimized(),
118 | {
119 | name: 'no-deprecations',
120 | npm: {
121 | devDependencies: {
122 | 'ember-deprecation-error': '*',
123 | },
124 | },
125 | },
126 | {
127 | name: 'ember-release-no-deprecations',
128 | npm: {
129 | devDependencies: {
130 | 'ember-source': await getChannelURL('release'),
131 | 'ember-deprecation-error': '*',
132 | },
133 | overrides: {
134 | 'ember-source': '$ember-source',
135 | },
136 | },
137 | },
138 | ],
139 | };
140 | };
141 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-showdown-prism",
3 | "version": "4.4.0",
4 | "description": "The default blueprint for ember-cli addons.",
5 | "keywords": [
6 | "ember-addon"
7 | ],
8 | "repository": "https://github.com/empress/ember-showdown-prism",
9 | "license": "MIT",
10 | "author": "",
11 | "directories": {
12 | "doc": "doc",
13 | "test": "tests"
14 | },
15 | "scripts": {
16 | "build": "ember build --environment=production",
17 | "ember-compatibility-test": "ember try:each",
18 | "lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
19 | "lint:css": "stylelint \"**/*.css\"",
20 | "lint:css:fix": "concurrently \"npm:lint:css -- --fix\"",
21 | "lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"",
22 | "lint:hbs": "ember-template-lint .",
23 | "lint:hbs:fix": "ember-template-lint . --fix",
24 | "lint:js": "eslint . --cache",
25 | "lint:js:fix": "eslint . --fix",
26 | "start": "ember serve",
27 | "test": "concurrently \"npm:lint\" \"npm:test:*\" --names \"lint,test:\"",
28 | "test:ember": "ember test"
29 | },
30 | "dependencies": {
31 | "broccoli-funnel": "^3.0.1",
32 | "ember-auto-import": "^2.6.3",
33 | "ember-cli-babel": "^7.26.11",
34 | "ember-prism": "^0.13.0"
35 | },
36 | "devDependencies": {
37 | "@babel/eslint-parser": "^7.22.5",
38 | "@babel/plugin-proposal-decorators": "^7.22.5",
39 | "@ember/optional-features": "^2.0.0",
40 | "@ember/string": "^3.1.1",
41 | "@ember/test-helpers": "^3.0.3",
42 | "@embroider/test-setup": "^3.0.1",
43 | "@glimmer/component": "^1.1.2",
44 | "@glimmer/tracking": "^1.1.2",
45 | "@release-it-plugins/lerna-changelog": "^5.0.0",
46 | "broccoli-asset-rev": "^3.0.0",
47 | "concurrently": "^8.2.0",
48 | "ember-cli": "~5.0.0",
49 | "ember-cli-clean-css": "^2.0.0",
50 | "ember-cli-dependency-checker": "^3.3.1",
51 | "ember-cli-fastboot": "^4.1.1",
52 | "ember-cli-htmlbars": "^6.2.0",
53 | "ember-cli-inject-live-reload": "^2.1.0",
54 | "ember-cli-showdown": "^7.0.0",
55 | "ember-cli-sri": "^2.1.1",
56 | "ember-cli-terser": "^4.0.2",
57 | "ember-fetch": "^8.1.1",
58 | "ember-load-initializers": "^2.1.2",
59 | "ember-page-title": "^7.0.0",
60 | "ember-qunit": "^7.0.0",
61 | "ember-resolver": "^10.1.0",
62 | "ember-source": "~5.0.0",
63 | "ember-source-channel-url": "^3.0.0",
64 | "ember-template-lint": "^5.10.1",
65 | "ember-try": "github:ember-cli/ember-try",
66 | "eslint": "^8.42.0",
67 | "eslint-config-prettier": "^8.8.0",
68 | "eslint-plugin-ember": "^11.8.0",
69 | "eslint-plugin-n": "^16.0.0",
70 | "eslint-plugin-prettier": "^4.2.1",
71 | "eslint-plugin-qunit": "^7.3.4",
72 | "lint-to-the-future": "^2.0.0",
73 | "lint-to-the-future-eslint": "^2.0.1",
74 | "loader.js": "^4.7.0",
75 | "prember": "^2.0.0",
76 | "prettier": "^2.8.8",
77 | "qunit": "^2.19.4",
78 | "qunit-dom": "^2.0.0",
79 | "release-it": "^15.5.0",
80 | "showdown": "^1.9.1",
81 | "stylelint": "^15.7.0",
82 | "stylelint-config-standard": "^33.0.0",
83 | "stylelint-prettier": "^3.0.0",
84 | "webpack": "^5.86.0"
85 | },
86 | "peerDependencies": {
87 | "ember-source": "^3.16.0 || >= 4.0.0",
88 | "showdown": ">1.0.0"
89 | },
90 | "engines": {
91 | "node": "16.* || >= 18"
92 | },
93 | "publishConfig": {
94 | "registry": "https://registry.npmjs.org"
95 | },
96 | "ember": {
97 | "edition": "octane"
98 | },
99 | "ember-addon": {
100 | "configPath": "tests/dummy/config"
101 | },
102 | "release-it": {
103 | "plugins": {
104 | "@release-it-plugins/lerna-changelog": {
105 | "infile": "CHANGELOG.md",
106 | "launchEditor": true
107 | }
108 | },
109 | "git": {
110 | "tagName": "v${version}"
111 | },
112 | "github": {
113 | "release": true,
114 | "tokenRef": "GITHUB_AUTH"
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/addon/initializers/showdown-extension.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable prettier/prettier */
2 | /* global Prism */
3 | import showdown from 'showdown';
4 | import { assert } from '@ember/debug';
5 |
6 | import { setup } from 'ember-prism';
7 |
8 | setup();
9 |
10 | // taken from prismjs, regex to detect newlines in text
11 | const NEW_LINE_EXP = /\n(?!$)/g;
12 |
13 | function getLineNumbersHTML(index, codeblock) {
14 | let match = codeblock.match(NEW_LINE_EXP);
15 | let linesNum = match ? match.length + 1 : 1;
16 | let lines = '';
17 | for (let i = 1; i < linesNum + 1; i++) {
18 | let id = `C${index}_L${i}`;
19 | lines += ``
20 | }
21 |
22 | return `${lines}`;
23 | }
24 |
25 | function stripQuotes(string) {
26 | if(string?.startsWith('"') && string?.endsWith('"')) {
27 | return string.substring(1, string.length - 1);
28 | }
29 | return string;
30 | }
31 |
32 | function diffInfo(args, codeblock) {
33 | if (args) {
34 | let lines = codeblock.split('\n');
35 |
36 | args.forEach(pD => {
37 | let operator = pD[0];
38 | let lineNo = +(pD.replace(operator, ''));
39 | let text = lines[lineNo - 1];
40 | if (operator === '+') {
41 | lines[lineNo - 1] = `+${text}`;
42 | } else {
43 | lines[lineNo - 1] = `-${text}`;
44 | }
45 | });
46 | codeblock = lines.join('\n');
47 | }
48 | return codeblock;
49 | }
50 |
51 | export function initialize(/* application */) {
52 | showdown.subParser('githubCodeBlocks', function (text, options, globals) {
53 | // early exit if option is not enabled
54 | if (!options.ghCodeBlocks) {
55 | return text;
56 | }
57 |
58 | text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals);
59 |
60 | text += '¨0';
61 |
62 | let idCounter = 1;
63 | text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\n`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function (wholeMatch, delim, languageBlock, inputCodeblock) {
64 | var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
65 |
66 | let codeblock = inputCodeblock;
67 |
68 | // First parse the github code block
69 | // codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
70 | codeblock = showdown.subParser('detab')(codeblock, options, globals);
71 | codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
72 | codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
73 |
74 | let match = languageBlock.match(/(\w+) ?(\{([^}]*)\})?/);
75 | let language = '';
76 | let attributeString = '';
77 |
78 | if(match && match[1]) {
79 | language = match[1];
80 | }
81 |
82 | if (match && match[3]) {
83 | attributeString = match[3];
84 | }
85 |
86 | let attributes = {};
87 |
88 | attributeString.split(' ').forEach(attribute => {
89 | let keyValue = attribute.split('=');
90 | attributes[keyValue[0]] = stripQuotes(keyValue[1]);
91 | });
92 |
93 | let lineNumbersHTML = getLineNumbersHTML(idCounter, codeblock);
94 | idCounter++;
95 |
96 | let diffInfoArgs = attributes['data-diff']?.split(',');
97 |
98 | assert(`Language "${language}" not found. Have you configured Prism correctly?`, !language || Prism.languages[language]);
99 |
100 | if (language && Prism.languages[language]) {
101 | // Restore dollar signs & tremas temporarily so Prism won't highlight this
102 | // See https://github.com/showdownjs/showdown/blob/a9f38b6f057284460d6447371f3dc5dea999c0a6/src/converter.js#L285 for more info
103 | codeblock = codeblock.replace(/¨D/g, '$$');
104 | codeblock = codeblock.replace(/¨T/g, '¨');
105 |
106 | let highlightedCodeBlock = Prism.highlight(codeblock, Prism.languages[language], language) + end;
107 | highlightedCodeBlock = diffInfo(diffInfoArgs, highlightedCodeBlock);
108 | codeblock = `${highlightedCodeBlock}${lineNumbersHTML}
`;
109 |
110 | // Convert to the special characters Showdown uses again
111 | codeblock = codeblock.replace(/¨/g, '¨T');
112 | codeblock = codeblock.replace(/\$/g, '¨D');
113 |
114 | if(attributes['data-filename']) {
115 | codeblock = `${attributes['data-filename'] || ''}${codeblock}
`;
116 | }
117 | } else {
118 | codeblock = diffInfo(diffInfoArgs, codeblock);
119 | codeblock = `${codeblock}${lineNumbersHTML}
`;
120 | }
121 |
122 | codeblock = showdown.subParser('hashBlock')(codeblock, options, globals);
123 |
124 | // Since GHCodeblocks can be false positives, we need to
125 | // store the primitive text and the parsed text in a global var,
126 | // and then return a token
127 | return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
128 | });
129 |
130 | // attacklab: strip sentinel
131 | text = text.replace(/¨0/, '');
132 |
133 | return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals);
134 | });
135 | }
136 |
137 | export default {
138 | initialize
139 | };
140 |
--------------------------------------------------------------------------------