quoteSelection
This commit is contained in:
Коммит
1501ab0a14
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"env": {
|
||||
"esm": {
|
||||
"presets": [
|
||||
["es2015", {"modules": false}],
|
||||
"flow"
|
||||
]
|
||||
},
|
||||
"umd": {
|
||||
"plugins": [
|
||||
"transform-es2015-modules-umd"
|
||||
],
|
||||
"presets": ["es2015", "flow"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": [
|
||||
"plugin:github/es6",
|
||||
"plugin:github/browser",
|
||||
"plugin:github/flow"
|
||||
],
|
||||
"parser": "babel-eslint"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
[ignore]
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
|
||||
[options]
|
||||
|
||||
[lints]
|
|
@ -0,0 +1,2 @@
|
|||
dist
|
||||
node_modules
|
|
@ -0,0 +1,9 @@
|
|||
language: node_js
|
||||
sudo: required
|
||||
node_js:
|
||||
- "node"
|
||||
addons:
|
||||
chrome: stable
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
|
@ -0,0 +1,20 @@
|
|||
Copyright (c) 2018 GitHub, Inc.
|
||||
|
||||
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:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
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.
|
|
@ -0,0 +1,52 @@
|
|||
# `quoteSelection`
|
||||
|
||||
Add selected text to a text area as a markdown quote.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ npm install @github/quote-selection
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import quoteSelection from '@github/quote-selection'
|
||||
quoteSelection(quotableContainer, textarea)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### HTML
|
||||
|
||||
```html
|
||||
<div class="js-quote-selection"><p>Text to quote</p></div>
|
||||
<textarea class="js-textarea"></textarea>
|
||||
```
|
||||
|
||||
### JS
|
||||
|
||||
```js
|
||||
import quoteSelection from '@github/quote-selection'
|
||||
|
||||
document.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'r' && !event.metaKey && !event.ctrlKey && !event.altKey) {
|
||||
const quoted = quoteSelection(
|
||||
document.querySelector('.js-quote-selection'),
|
||||
document.querySelector('.js-textarea')
|
||||
)
|
||||
if (quoted) event.preventDefault()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```
|
||||
npm install
|
||||
npm test
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Distributed under the MIT license. See LICENSE for details.
|
|
@ -0,0 +1,32 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>quote-selection demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Select and press <kbd>r</kbd> to quote. Selecting this line does not quote.<p>
|
||||
<hr>
|
||||
<div class="js-quote-selection">
|
||||
<h4>Blame</h4>
|
||||
<p>The "blame" feature in Git describes the last modification to each line of a file, which generally displays the revision, author and time. This is helpful, for example, in tracking down when a feature was added, or which commit led to a particular bug.</p>
|
||||
|
||||
<h4>Branch</h4>
|
||||
<p>A branch is a parallel version of a repository. It is contained within the repository, but does not affect the primary or <code>master</code> branch allowing you to work freely without disrupting the "live" version. When you've made the changes you want to make, you can merge your branch back into the <code>master</code> branch to publish your changes.</p>
|
||||
<textarea class="js-textarea" cols="50" rows="10"></textarea>
|
||||
</div>
|
||||
<script type="module">
|
||||
import quoteSelection from '../dist/quote-selection.esm.js'
|
||||
|
||||
document.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'r' && !event.metaKey && !event.ctrlKey && !event.altKey) {
|
||||
const quoted = quoteSelection(
|
||||
document.querySelector('.js-quote-selection'),
|
||||
document.querySelector('.js-textarea')
|
||||
)
|
||||
if (quoted) event.preventDefault()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "@github/quote-selection",
|
||||
"description": "Add selected text to a text area as a markdown quote.",
|
||||
"version": "0.0.1",
|
||||
"main": "dist/quote-selection.umd.js",
|
||||
"module": "dist/quote-selection.esm.js",
|
||||
"license": "MIT",
|
||||
"repository": "github/quote-selection",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rm -rf dist",
|
||||
"lint": "eslint quote-selection.js test/ && flow check",
|
||||
"prebuild": "npm run clean && npm run lint && mkdir dist",
|
||||
"build-umd": "BABEL_ENV=umd babel quote-selection.js -o dist/quote-selection.umd.js",
|
||||
"build-esm": "BABEL_ENV=esm babel quote-selection.js -o dist/quote-selection.esm.js",
|
||||
"build": "npm run build-umd && npm run build-esm",
|
||||
"pretest": "npm run build",
|
||||
"test": "karma start test/karma.config.js",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-flow": "^6.23.0",
|
||||
"chai": "^4.1.2",
|
||||
"eslint": "^5.0.1",
|
||||
"eslint-plugin-github": "1.0.0",
|
||||
"flow-bin": "^0.75.0",
|
||||
"karma": "^2.0.0",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"mocha": "^5.0.5"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
module.exports = require('eslint-plugin-github/prettier.config')
|
|
@ -0,0 +1,38 @@
|
|||
/* @flow */
|
||||
|
||||
export default function quoteSelection(container: HTMLElement, field: HTMLTextAreaElement): boolean {
|
||||
const selection = window.getSelection()
|
||||
let selectionText = selection.toString().trim()
|
||||
if (!selectionText) return false
|
||||
|
||||
let focusNode = selection.focusNode
|
||||
if (!focusNode) return false
|
||||
|
||||
if (focusNode.nodeType !== Node.ELEMENT_NODE) focusNode = focusNode.parentNode
|
||||
if (!(focusNode instanceof Element)) return false
|
||||
|
||||
if (!container.contains(focusNode)) return false
|
||||
|
||||
const eventDetail = {selection, selectionText}
|
||||
const fireEvent = container.dispatchEvent(
|
||||
new CustomEvent('quote-selection', {
|
||||
bubble: true,
|
||||
detail: eventDetail
|
||||
})
|
||||
)
|
||||
if (!fireEvent) return true
|
||||
|
||||
selectionText = eventDetail.selectionText
|
||||
let quotedText = `> ${selectionText.replace(/\n/g, '\n> ')}\n\n`
|
||||
if (field.value) {
|
||||
quotedText = `${field.value}\n\n${quotedText}`
|
||||
}
|
||||
|
||||
field.value = quotedText
|
||||
|
||||
field.focus()
|
||||
field.selectionStart = field.value.length
|
||||
field.scrollTop = field.scrollHeight
|
||||
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"rules": {
|
||||
"flowtype/require-valid-file-annotation": "off"
|
||||
},
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"globals": {
|
||||
"assert": true
|
||||
},
|
||||
"extends": "../.eslintrc.json"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
module.exports = function(config) {
|
||||
config.set({
|
||||
frameworks: ['mocha', 'chai'],
|
||||
files: ['../dist/quote-selection.umd.js', 'test.js'],
|
||||
reporters: ['mocha'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
browsers: ['ChromeHeadless'],
|
||||
autoWatch: false,
|
||||
singleRun: true,
|
||||
concurrency: Infinity
|
||||
})
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/* global quoteSelection */
|
||||
|
||||
describe('quote-selection', function() {
|
||||
describe('with quotable selection', function() {
|
||||
beforeEach(function() {
|
||||
document.body.innerHTML = `
|
||||
<p id="not-quotable">Not quotable text</p>
|
||||
<p id="quotable">Quotable text</p>
|
||||
<textarea>Has text</textarea>
|
||||
`
|
||||
const el = document.querySelector('#quotable')
|
||||
window.getSelection = function() {
|
||||
return {
|
||||
focusNode: el,
|
||||
toString: () => el.textContent
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(function() {
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
it('textarea is updated', function(done) {
|
||||
const container = document.querySelector('#quotable')
|
||||
const textarea = document.querySelector('textarea')
|
||||
|
||||
container.addEventListener('quote-selection', function() {
|
||||
done()
|
||||
})
|
||||
|
||||
const quoted = quoteSelection.default(container, textarea)
|
||||
assert(quoted)
|
||||
assert.equal(textarea.value, 'Has text\n\n> Quotable text\n\n')
|
||||
})
|
||||
})
|
||||
|
||||
describe('with non-quotable selection', function() {
|
||||
beforeEach(function() {
|
||||
document.body.innerHTML = `
|
||||
<p id="not-quotable">Not quotable text</p>
|
||||
<p id="quotable">Quotable text</p>
|
||||
<textarea>Has text</textarea>
|
||||
`
|
||||
const el = document.querySelector('#not-quotable')
|
||||
window.getSelection = function() {
|
||||
return {
|
||||
focusNode: el,
|
||||
toString: () => el.textContent
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(function() {
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
it('textarea is not updated', function() {
|
||||
const container = document.querySelector('#quotable')
|
||||
const textarea = document.querySelector('textarea')
|
||||
const quoted = quoteSelection.default(container, textarea)
|
||||
|
||||
assert(!quoted)
|
||||
assert.equal(textarea.value, 'Has text')
|
||||
})
|
||||
})
|
||||
})
|
Загрузка…
Ссылка в новой задаче