diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index c1290bb..0000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -coverage/ -dist/ -node_modules diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index eacf1c3..0000000 --- a/.eslintrc +++ /dev/null @@ -1,117 +0,0 @@ -env: - node: true - -plugins: - - nodeca - -rules: - block-scoped-var: 2 - brace-style: [ 2, '1tbs', { allowSingleLine: true } ] - comma-spacing: 2 - comma-style: 2 - consistent-this: [ 2, self ] - consistent-return: 2 - curly: 2 - # default-case: 2 - dot-notation: 2 - eol-last: 2 - eqeqeq: 2 - guard-for-in: 2 - handle-callback-err: 2 - max-depth: [ 1, 6 ] - max-nested-callbacks: [ 1, 4 ] - # string can exceed 80 chars, but should not overflow github website :) - max-len: [ 2, 120, 1000 ] - new-cap: 2 - new-parens: 2 - no-alert: 2 - no-array-constructor: 2 - no-bitwise: 2 - no-caller: 2 - no-catch-shadow: 2 - no-comma-dangle: 2 - no-cond-assign: 2 - no-console: 1 - no-constant-condition: 2 - no-control-regex: 2 - no-debugger: 2 - no-delete-var: 2 - no-dupe-keys: 2 - no-div-regex: 2 - no-empty: 2 - no-empty-class: 2 - no-empty-label: 2 - no-else-return: 2 - no-eq-null: 2 - no-ex-assign: 2 - no-extend-native: 2 - no-extra-bind: 2 - no-extra-boolean-cast: 2 - no-extra-semi: 2 - no-extra-strict: 2 - no-eval: 2 - no-floating-decimal: 2 - no-func-assign: 2 - no-implied-eval: 2 - no-inner-declarations: 2 - no-invalid-regexp: 2 - no-irregular-whitespace: 2 - no-label-var: 2 - no-labels: 2 - no-lone-blocks: 2 - no-lonely-if: 2 - no-loop-func: 2 - no-mixed-requires: 2 - no-mixed-spaces-and-tabs: 2 - no-multi-str: 2 - no-native-reassign: 2 - no-negated-in-lhs: 2 - no-new: 2 - no-new-func: 2 - no-new-object: 2 - no-new-require: 2 - no-new-wrappers: 2 - no-obj-calls: 2 - no-octal: 2 - no-octal-escape: 2 - no-path-concat: 2 - no-redeclare: 2 - no-regex-spaces: 2 - no-reserved-keys: 2 - no-return-assign: 2 - no-script-url: 2 - no-sequences: 2 - no-shadow: 2 - no-shadow-restricted-names: 2 - no-space-before-semi: 2 - no-sparse-arrays: 2 - no-trailing-spaces: 2 - no-undef: 2 - no-undef-init: 2 - no-undefined: 2 - no-unreachable: 2 - no-unused-expressions: 2 - no-unused-vars: 2 - no-use-before-define: 2 - no-with: 2 - no-wrap-func: 2 - quotes: [ 2, single, avoid-escape ] - radix: 2 - semi: 2 - space-after-keywords: [ 2, always, , { "checkFunctionKeyword": true } ] - space-before-blocks: 2 - space-in-brackets: [ 2, always, { propertyName: false } ] - space-in-parens: [ 2, never ] - space-infix-ops: 2 - space-return-throw-case: 2 - space-unary-ops: 2 - spaced-line-comment: [ 2, always, { exceptions: [ '/' ] } ] - strict: 2 - use-isnan: 2 - yoda: 2 - valid-typeof: 2 - - # - # Our custom rules - # - nodeca/indent: [ 2, spaces, 2 ] diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000..1cd8ca5 --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,22 @@ +extends: standard + +overrides: + - + files: [ '*.mjs' ] + rules: + no-restricted-globals: [ 2, require, __dirname ] + - + files: [ 'test/**' ] + env: { mocha: true } + - + files: [ 'lib/**', 'index.mjs' ] + parserOptions: { ecmaVersion: 2015 } + +ignorePatterns: + - demo/ + - dist/ + - benchmark/extra/ + +rules: + camelcase: 0 + no-multi-spaces: 0 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..b4bceaf --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + + - package-ecosystem: npm + directory: / + schedule: + interval: daily + allow: + - dependency-type: production diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..241583b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,34 @@ +name: CI + +on: + push: + pull_request: + schedule: + - cron: '0 0 * * 3' + +jobs: + test: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [ '18' ] + + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - run: npm install + + - name: Test + run: npm test + + - name: Upload coverage report to coveralls.io + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 4c444c6..06c3eac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ node_modules/ coverage/ -*.log +dist/ diff --git a/.npmignore b/.npmignore deleted file mode 100644 index a329090..0000000 --- a/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -coverage/ -support/ -test/ -Makefile -.* -*.log diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c1c69c5..0000000 --- a/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: node_js -node_js: - - '0.10' -script: make test-ci diff --git a/CHANGELOG.md b/CHANGELOG.md index cb6f870..16ebfd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +2.0.0 / 2023-12-03 +------------------ + +- Rewrite to ESM. +- Remove `dist/` from repo (build on package publish). + + 1.0.0 / 2015-03-12 ------------------ diff --git a/Makefile b/Makefile deleted file mode 100644 index bf15d66..0000000 --- a/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -NPM_PACKAGE := $(shell node -e 'process.stdout.write(require("./package.json").name)') -NPM_VERSION := $(shell node -e 'process.stdout.write(require("./package.json").version)') - -TMP_PATH := /tmp/${NPM_PACKAGE}-$(shell date +%s) - -REMOTE_NAME ?= origin -REMOTE_REPO ?= $(shell git config --get remote.${REMOTE_NAME}.url) - -CURR_HEAD := $(firstword $(shell git show-ref --hash HEAD | cut -b -6) master) -GITHUB_PROJ := https://github.com//markdown-it/${NPM_PACKAGE} - - -lint: - ./node_modules/.bin/eslint --reset . - -test: lint - ./node_modules/.bin/mocha -R spec - -coverage: - rm -rf coverage - ./node_modules/.bin/istanbul cover node_modules/.bin/_mocha - -test-ci: lint - istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage - -browserify: - rm -rf ./dist - mkdir dist - # Browserify - ( printf "/*! ${NPM_PACKAGE} ${NPM_VERSION} ${GITHUB_PROJ} @license MIT */" ; \ - ./node_modules/.bin/browserify ./ -s markdownitSup \ - ) > dist/markdown-it-sup.js - # Minify - ./node_modules/.bin/uglifyjs dist/markdown-it-sup.js -b beautify=false,ascii-only=true -c -m \ - --preamble "/*! ${NPM_PACKAGE} ${NPM_VERSION} ${GITHUB_PROJ} @license MIT */" \ - > dist/markdown-it-sup.min.js - -.PHONY: lint test coverage -.SILENT: lint test diff --git a/bower.json b/bower.json deleted file mode 100644 index e7a606b..0000000 --- a/bower.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "markdown-it-sup", - "main": "dist/markdown-it-sup.js", - "homepage": "https://github.com/markdown-it/markdown-it-sup", - "description": " tag for markdown-it markdown parser.", - "keywords": [ - "markdown-it-plugin", - "markdown-it", - "markdown", - "superscript", - "sup" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "benchmark", - "bower_components", - "coverage", - "demo", - "docs", - "lib", - "node_modules", - "support", - "test", - "Makefile", - "index*" - ] -} diff --git a/dist/markdown-it-sup.js b/dist/markdown-it-sup.js deleted file mode 100644 index d4dc0e6..0000000 --- a/dist/markdown-it-sup.js +++ /dev/null @@ -1,69 +0,0 @@ -/*! markdown-it-sup 1.0.0 https://github.com//markdown-it/markdown-it-sup @license MIT */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.markdownitSup = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o?@[\]^_`{|}~-])/g; - -function superscript(state, silent) { - var found, - content, - token, - max = state.posMax, - start = state.pos; - - if (state.src.charCodeAt(start) !== 0x5E/* ^ */) { return false; } - if (silent) { return false; } // don't run any pairs in validation mode - if (start + 2 >= max) { return false; } - - state.pos = start + 1; - - while (state.pos < max) { - if (state.src.charCodeAt(state.pos) === 0x5E/* ^ */) { - found = true; - break; - } - - state.md.inline.skipToken(state); - } - - if (!found || start + 1 === state.pos) { - state.pos = start; - return false; - } - - content = state.src.slice(start + 1, state.pos); - - // don't allow unescaped spaces/newlines inside - if (content.match(/(^|[^\\])(\\\\)*\s/)) { - state.pos = start; - return false; - } - - // found! - state.posMax = state.pos; - state.pos = start + 1; - - // Earlier we checked !silent, but this implementation does not need it - token = state.push('sup_open', 'sup', 1); - token.markup = '^'; - - token = state.push('text', '', 0); - token.content = content.replace(UNESCAPE_RE, '$1'); - - token = state.push('sup_close', 'sup', -1); - token.markup = '^'; - - state.pos = state.posMax + 1; - state.posMax = max; - return true; -} - - -module.exports = function sup_plugin(md) { - md.inline.ruler.after('emphasis', 'sup', superscript); -}; - -},{}]},{},[1])(1) -}); \ No newline at end of file diff --git a/dist/markdown-it-sup.min.js b/dist/markdown-it-sup.min.js deleted file mode 100644 index 67da65c..0000000 --- a/dist/markdown-it-sup.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! markdown-it-sup 1.0.0 https://github.com//markdown-it/markdown-it-sup @license MIT */ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.markdownitSup=e()}}(function(){return function e(r,o,n){function t(i,p){if(!o[i]){if(!r[i]){var u="function"==typeof require&&require;if(!p&&u)return u(i,!0);if(s)return s(i,!0);var f=new Error("Cannot find module '"+i+"'");throw f.code="MODULE_NOT_FOUND",f}var a=o[i]={exports:{}};r[i][0].call(a.exports,function(e){var o=r[i][1][e];return t(o?o:e)},a,a.exports,e,r,o,n)}return o[i].exports}for(var s="function"==typeof require&&require,i=0;i=i)return!1;for(e.pos=p+1;e.pos?@[\]^_`{|}~-])/g;r.exports=function(e){e.inline.ruler.after("emphasis","sup",o)}},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/index.js b/index.js deleted file mode 100644 index 20b9562..0000000 --- a/index.js +++ /dev/null @@ -1,65 +0,0 @@ -// Process ^superscript^ - -'use strict'; - -// same as UNESCAPE_MD_RE plus a space -var UNESCAPE_RE = /\\([ \\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g; - -function superscript(state, silent) { - var found, - content, - token, - max = state.posMax, - start = state.pos; - - if (state.src.charCodeAt(start) !== 0x5E/* ^ */) { return false; } - if (silent) { return false; } // don't run any pairs in validation mode - if (start + 2 >= max) { return false; } - - state.pos = start + 1; - - while (state.pos < max) { - if (state.src.charCodeAt(state.pos) === 0x5E/* ^ */) { - found = true; - break; - } - - state.md.inline.skipToken(state); - } - - if (!found || start + 1 === state.pos) { - state.pos = start; - return false; - } - - content = state.src.slice(start + 1, state.pos); - - // don't allow unescaped spaces/newlines inside - if (content.match(/(^|[^\\])(\\\\)*\s/)) { - state.pos = start; - return false; - } - - // found! - state.posMax = state.pos; - state.pos = start + 1; - - // Earlier we checked !silent, but this implementation does not need it - token = state.push('sup_open', 'sup', 1); - token.markup = '^'; - - token = state.push('text', '', 0); - token.content = content.replace(UNESCAPE_RE, '$1'); - - token = state.push('sup_close', 'sup', -1); - token.markup = '^'; - - state.pos = state.posMax + 1; - state.posMax = max; - return true; -} - - -module.exports = function sup_plugin(md) { - md.inline.ruler.after('emphasis', 'sup', superscript); -}; diff --git a/index.mjs b/index.mjs new file mode 100644 index 0000000..035899c --- /dev/null +++ b/index.mjs @@ -0,0 +1,60 @@ +// Process ^superscript^ + +// same as UNESCAPE_MD_RE plus a space +const UNESCAPE_RE = /\\([ \\!"#$%&'()*+,./:;<=>?@[\]^_`{|}~-])/g + +function superscript (state, silent) { + const max = state.posMax + const start = state.pos + + if (state.src.charCodeAt(start) !== 0x5E/* ^ */) { return false } + if (silent) { return false } // don't run any pairs in validation mode + if (start + 2 >= max) { return false } + + state.pos = start + 1 + let found = false + + while (state.pos < max) { + if (state.src.charCodeAt(state.pos) === 0x5E/* ^ */) { + found = true + break + } + + state.md.inline.skipToken(state) + } + + if (!found || start + 1 === state.pos) { + state.pos = start + return false + } + + const content = state.src.slice(start + 1, state.pos) + + // don't allow unescaped spaces/newlines inside + if (content.match(/(^|[^\\])(\\\\)*\s/)) { + state.pos = start + return false + } + + // found! + state.posMax = state.pos + state.pos = start + 1 + + // Earlier we checked !silent, but this implementation does not need it + const token_so = state.push('sup_open', 'sup', 1) + token_so.markup = '^' + + const token_t = state.push('text', '', 0) + token_t.content = content.replace(UNESCAPE_RE, '$1') + + const token_sc = state.push('sup_close', 'sup', -1) + token_sc.markup = '^' + + state.pos = state.posMax + 1 + state.posMax = max + return true +} + +export default function sup_plugin (md) { + md.inline.ruler.after('emphasis', 'sup', superscript) +}; diff --git a/package.json b/package.json index 1c0a893..6571fda 100644 --- a/package.json +++ b/package.json @@ -9,30 +9,41 @@ "superscript", "sup" ], - "homepage": "https://github.com/markdown-it/markdown-it-sup", - "repository": { - "type": "git", - "url": "git://github.com/markdown-it/markdown-it-sup.git" - }, - "bugs": { - "url": "https://github.com/markdown-it/markdown-it-sup/issues" - }, + "repository": "markdown-it/markdown-it-sup", "license": "MIT", - "main": "index.js", + "main": "dist/index.cjs.js", + "module": "index.mjs", + "exports": { + ".": { + "require": "./dist/index.cjs.js", + "import": "./index.mjs" + }, + "./*": { + "require": "./*", + "import": "./*" + } + }, + "files": [ + "index.mjs", + "lib/", + "dist/" + ], "scripts": { - "test": "make test" + "lint": "eslint .", + "build": "rollup -c", + "test": "npm run lint && npm run build && c8 --exclude dist --exclude test -r text -r html -r lcov mocha", + "prepublishOnly": "npm run lint && npm run build" }, "devDependencies": { - "browserify": "*", - "coveralls": "^2.11.2", - "eslint": "0.10.2", - "eslint-plugin-nodeca": "^1.0.0", - "istanbul": "*", - "lodash": "*", - "markdown-it": "^4.0.0", - "markdown-it-testgen": "~0.1.0", - "mocha": "*", - "request": "*", - "uglify-js": "*" + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-terser": "^0.4.4", + "c8": "^8.0.1", + "eslint": "^8.55.0", + "eslint-config-standard": "^17.1.0", + "markdown-it": "^13.0.2", + "markdown-it-testgen": "^0.1.6", + "mocha": "^10.2.0", + "rollup": "^4.6.1" } } diff --git a/rollup.config.mjs b/rollup.config.mjs new file mode 100644 index 0000000..000ffdf --- /dev/null +++ b/rollup.config.mjs @@ -0,0 +1,74 @@ +import resolve from '@rollup/plugin-node-resolve' +import terser from '@rollup/plugin-terser' +import { babel } from '@rollup/plugin-babel' +import { readFileSync } from 'fs' + +const pkg = JSON.parse(readFileSync(new URL('package.json', import.meta.url))) + +function globalName (name) { + const parts = name.split('-') + for (let i = 2; i < parts.length; i++) { + parts[i] = parts[i][0].toUpperCase() + parts[i].slice(1) + } + return parts.join('') +} + +const config_umd_full = { + input: 'index.mjs', + output: [ + { + file: `dist/${pkg.name}.js`, + format: 'umd', + name: globalName(pkg.name), + plugins: [ + // Here terser is used only to force ascii output + terser({ + mangle: false, + compress: false, + format: { comments: 'all', beautify: true, ascii_only: true, indent_level: 2 } + }) + ] + }, + { + file: `dist/${pkg.name}.min.js`, + format: 'umd', + name: globalName(pkg.name), + plugins: [ + terser({ + format: { ascii_only: true } + }) + ] + } + ], + plugins: [ + resolve(), + babel({ babelHelpers: 'bundled' }), + { + banner () { + return `/*! ${pkg.name} ${pkg.version} https://github.com/${pkg.repository} @license ${pkg.license} */` + } + } + ] +} + +const config_cjs_no_deps = { + input: 'index.mjs', + output: { + file: 'dist/index.cjs.js', + format: 'cjs' + }, + external: Object.keys(pkg.dependencies || {}), + plugins: [ + resolve(), + babel({ babelHelpers: 'bundled' }) + ] +} + +let config = [ + config_umd_full, + config_cjs_no_deps +] + +if (process.env.CJS_ONLY) config = [config_cjs_no_deps] + +export default config diff --git a/test/cjs.js b/test/cjs.js new file mode 100644 index 0000000..333a5e6 --- /dev/null +++ b/test/cjs.js @@ -0,0 +1,11 @@ +'use strict' +/* eslint-env mocha */ + +const assert = require('node:assert') +const fn = require('../') + +describe('CJS', () => { + it('require', () => { + assert.ok(typeof fn === 'function') + }) +}) diff --git a/test/test.js b/test/test.js deleted file mode 100644 index 2359adf..0000000 --- a/test/test.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - - -var path = require('path'); -var generate = require('markdown-it-testgen'); - -/*eslint-env mocha*/ - -describe('markdown-it-sup', function () { - var md = require('markdown-it')() - .use(require('../')); - - generate(path.join(__dirname, 'fixtures/sup.txt'), md); -}); diff --git a/test/test.mjs b/test/test.mjs new file mode 100644 index 0000000..440a671 --- /dev/null +++ b/test/test.mjs @@ -0,0 +1,11 @@ +import { fileURLToPath } from 'node:url' +import markdownit from 'markdown-it' +import generate from 'markdown-it-testgen' + +import sup from '../index.mjs' + +describe('markdown-it-sup', function () { + const md = markdownit().use(sup) + + generate(fileURLToPath(new URL('fixtures/sup.txt', import.meta.url)), md) +})