index.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Dependencies
  2. // =============================================================================
  3. // eslint-disable-next-line no-unused-vars
  4. import styles from './styles.css'
  5. // Plugin
  6. // =============================================================================
  7. function docsifyCopyCode(hook, vm) {
  8. hook.doneEach(function () {
  9. const targetElms = Array.apply(null, document.querySelectorAll('pre[data-lang]'))
  10. const i18n = {
  11. buttonText: 'Copy to clipboard',
  12. errorText: 'Error',
  13. successText: 'Copied',
  14. }
  15. // Update i18n strings based on options and location.href
  16. if (vm.config.copyCode) {
  17. Object.keys(i18n).forEach(key => {
  18. const textValue = vm.config.copyCode[key]
  19. if (typeof textValue === 'string') {
  20. i18n[key] = textValue
  21. } else if (typeof textValue === 'object') {
  22. Object.keys(textValue).some(match => {
  23. const isMatch = location.href.indexOf(match) > -1
  24. i18n[key] = isMatch ? textValue[match] : i18n[key]
  25. return isMatch
  26. })
  27. }
  28. })
  29. }
  30. const template = [
  31. '<button class="docsify-copy-code-button">',
  32. `<span class="label">${i18n.buttonText}</span>`,
  33. `<span class="error">${i18n.errorText}</span>`,
  34. `<span class="success">${i18n.successText}</span>`,
  35. '</button>',
  36. ].join('')
  37. targetElms.forEach(elm => {
  38. elm.insertAdjacentHTML('beforeend', template)
  39. })
  40. })
  41. hook.mounted(function () {
  42. const listenerHost = document.querySelector('.content')
  43. listenerHost.addEventListener('click', function (evt) {
  44. const isCopyCodeButton = evt.target.classList.contains('docsify-copy-code-button')
  45. if (isCopyCodeButton) {
  46. const buttonElm = evt.target.tagName === 'BUTTON' ? evt.target : evt.target.parentNode
  47. const range = document.createRange()
  48. const preElm = buttonElm.parentNode
  49. const codeElm = preElm.querySelector('code')
  50. let selection = window.getSelection()
  51. range.selectNode(codeElm)
  52. selection.removeAllRanges()
  53. selection.addRange(range)
  54. try {
  55. // Copy selected text
  56. const successful = document.execCommand('copy')
  57. if (successful) {
  58. buttonElm.classList.add('success')
  59. setTimeout(function () {
  60. buttonElm.classList.remove('success')
  61. }, 1000)
  62. }
  63. } catch (err) {
  64. // eslint-disable-next-line
  65. console.error(`docsify-copy-code: ${err}`)
  66. buttonElm.classList.add('error')
  67. setTimeout(function () {
  68. buttonElm.classList.remove('error')
  69. }, 1000)
  70. }
  71. selection = window.getSelection()
  72. if (typeof selection.removeRange === 'function') {
  73. selection.removeRange(range)
  74. } else if (typeof selection.removeAllRanges === 'function') {
  75. selection.removeAllRanges()
  76. }
  77. }
  78. })
  79. })
  80. }
  81. // Deprecation warning for v1.x: stylesheet
  82. if (document.querySelector('link[href*="docsify-copy-code"]')) {
  83. // eslint-disable-next-line
  84. console.warn('[Deprecation] Link to external docsify-copy-code stylesheet is no longer necessary.')
  85. }
  86. // Deprecation warning for v1.x: init()
  87. window.DocsifyCopyCodePlugin = {
  88. init: function () {
  89. return function (hook, vm) {
  90. hook.ready(function () {
  91. // eslint-disable-next-line
  92. console.warn('[Deprecation] Manually initializing docsify-copy-code using window.DocsifyCopyCodePlugin.init() is no longer necessary.')
  93. })
  94. }
  95. },
  96. }
  97. window.$docsify = window.$docsify || {}
  98. window.$docsify.plugins = [docsifyCopyCode].concat(window.$docsify.plugins || [])