EdText.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <template>
  2. <div class="text-wrapper">
  3. <EdTextRefLink :uuid="uuid" :url="url" />
  4. <div
  5. class="tei"
  6. :class="{ active: uuid === textid }"
  7. :data-uuid="uuid"
  8. v-html="teiparsed"
  9. />
  10. </div>
  11. </template>
  12. <script>
  13. // import Vue from 'vue'
  14. import EdTextRefLink from './EdTextRefLink'
  15. export default {
  16. name: 'EdText',
  17. components: {
  18. EdTextRefLink
  19. },
  20. props: {
  21. tei: String,
  22. uuid: String,
  23. textid: String,
  24. extractid: String,
  25. url: String
  26. },
  27. data: () => ({
  28. template: null,
  29. html: null,
  30. pages: [],
  31. teiparsed: null
  32. }),
  33. watch: {
  34. tei: function (newtei, oldtei) {
  35. // console.log('tei watcher', oldtei, newtei)
  36. // we need this watcher to update display as route is changing
  37. // this.buildTemplate()
  38. this.parseTei()
  39. }
  40. },
  41. beforeMount () {
  42. // console.log('EdText beforeMount', this.tei)
  43. if (this.tei) {
  44. // this.buildTemplate()
  45. this.parseTei()
  46. }
  47. },
  48. // mounted () {
  49. // this.$emit('onNewPageBreaks', this.pages)
  50. // },
  51. methods: {
  52. // buildTemplate () {
  53. // // console.log('EdText buildTemplate: tei', this.tei)
  54. // // to get Vue.compile working we have to use the full build of vuejs
  55. // // https://vuejs.org/v2/guide/installation.html#Explanation-of-Different-Builds
  56. // // in /build/webpack.config.base.js alias -> 'vue': 'vue/dist/vue.js',
  57. // this.buildHtml()
  58. // this.template = Vue.compile(this.html)
  59. // this.$options.staticRenderFns = []
  60. // this._staticTrees = []
  61. // this.template.staticRenderFns.map(fn => (this.$options.staticRenderFns.push(fn)))
  62. // },
  63. // buildHtml () {
  64. // this.html = `<div` +
  65. // ` class="tei${this.uuid === this.textid ? ' active' : ''}"` +
  66. // ` data-uuid="${this.uuid}"` +
  67. // `>` +
  68. // `<a` +
  69. // ` href="http://${window.apipath}/items/${this.uuid}"` +
  70. // ` title="Copy to clipboard ${this.uuid}"` +
  71. // ` class="text-item-link"` +
  72. // ` @click.prevent="onClickCopyClipboard"` +
  73. // `>` +
  74. // `<span class="mdi mdi-open-in-new" />` +
  75. // `</a>` +
  76. // `${this.tei}</div>`
  77. // this.parseLinks()
  78. // this.parseFigures()
  79. // // this.parsePageBreaks()
  80. // // console.log('EdText: builded html', this.html)
  81. // },
  82. parseTei () {
  83. this.teiparsed = this.tei
  84. this.parseIndexItems()
  85. this.parseLinks()
  86. this.parseFigures()
  87. if (this.textid === this.uuid) {
  88. this.parseExtract()
  89. }
  90. },
  91. parseIndexItems () {
  92. let items = this.teiparsed.match(/<span[^>]*class="(persName|objectName|placeName)"[^>]*>[^<]+<\/span>/g)
  93. console.log('items', items)
  94. if (items) {
  95. let itemparts, icon, newspan
  96. for (var i = 0; i < items.length; i++) {
  97. itemparts = RegExp(/(<span[^>]*class="([^"]+)"[^>]*>)(.+)<\/span>/g).exec(items[i], 'g')
  98. // console.log('itemparts', itemparts)
  99. switch (itemparts[2]) {
  100. case 'placeName':
  101. icon = '<span class="index-item-icon mdi mdi-map-marker"></span>'
  102. break
  103. case 'objectName':
  104. icon = '<span class="index-item-icon mdi mdi-card-bulleted"></span>'
  105. break
  106. case 'persName':
  107. icon = '<span class="index-item-icon mdi mdi-account"></span>'
  108. break
  109. }
  110. // newspan = `${items[i]}&nbsp;${icon}`
  111. // newspan = `<span class="no-wrap">${items[i]}&nbsp;${icon}</span>`
  112. // newspan = `${itemparts[1]}${itemparts[3]}${'&#160;'}${icon}</span>`
  113. let words = itemparts[3].split(' ')
  114. let lastword = words.splice(words.length - 1, 1)
  115. newspan = `${itemparts[1]}${words.join(' ')} <span class="no-wrap">${lastword}&nbsp;${icon}</span></span>`
  116. this.teiparsed = this.teiparsed.replace(items[i], newspan)
  117. }
  118. }
  119. },
  120. parseLinks () {
  121. let links = this.teiparsed.match(/<a[^<]+<\/a>/g)
  122. // console.log('links', links)
  123. if (links) {
  124. // let domparser = new DOMParser()
  125. // let domlink
  126. let linkparts, newlink, uuid
  127. let index = null
  128. for (var i = 0; i < links.length; i++) {
  129. // console.log(`link ${i}:`, links[i])
  130. linkparts = RegExp(/<a class="(.+)" href="(.+)" data-index="(.+)">(.+)<\/a>/g).exec(links[i], 'g')
  131. // console.log('linkparts', linkparts)
  132. if (!linkparts) {
  133. console.warn(`link ${i} malformed:`, links[i])
  134. } else {
  135. index = linkparts[3]
  136. uuid = linkparts[2].replace('#', '')
  137. newlink = `<a` +
  138. ` class="${linkparts[1]} active-link"` +
  139. ` data-index="${index}"` +
  140. ` data-uuid="${uuid}"` +
  141. ` href="/${index}/${uuid}"` +
  142. ` @click.prevent="onClickRef"` +
  143. ` @keyup.enter="onClickRef"` +
  144. ` @mouseover="onHoverLink"` +
  145. ` @mouseleave="onLeaveLink"` +
  146. // prevent click on this one
  147. ` v-touch:tap.prevent="onTapLink"` +
  148. ` v-touch-class="'tapped'"` +
  149. `>${linkparts[4]}` +
  150. // `<sup class="mdi mdi-message-text-outline" />` +
  151. `</a>`
  152. // console.log('newlink', newlink)
  153. this.teiparsed = this.teiparsed.replace(links[i], newlink)
  154. }
  155. }
  156. // console.log('this.html', this.html)
  157. }
  158. },
  159. parseFigures () {
  160. // console.log('parseFigures this.tei', this.teiparsed)
  161. let imgs = this.teiparsed.match(/<img[^>]*>/g)
  162. console.log('imgs', imgs)
  163. if (imgs) {
  164. let imgparts, newsrc, newimg
  165. for (var i = 0; i < imgs.length; i++) {
  166. // console.log(`link ${i}:`, links[i])
  167. imgparts = RegExp(/<img src="(.+)" alt="(.+)">/g).exec(imgs[i], 'g')
  168. console.log('imgparts', imgparts)
  169. if (!imgparts) {
  170. console.warn(`img ${i} malformed:`, imgs[i])
  171. } else {
  172. newsrc = `${imgparts[1]}/full/1000,/0/native.jpg`
  173. newimg = `<img` +
  174. ` src="${newsrc}"` +
  175. ` alt="${imgparts[2]}"` +
  176. `/>`
  177. // console.log('newlink', newlink)
  178. this.teiparsed = this.teiparsed.replace(imgs[i], newimg)
  179. }
  180. }
  181. }
  182. },
  183. parseExtract () {
  184. console.log('Parse extract', this.extractid)
  185. // let regexp = RegExp(this.extract, 'gim')
  186. let regexp = RegExp(`<span[^>]* id="${this.extractid}"[^>]*>[^<]*</span>`)
  187. // let regexp = RegExp(`<(\w+)((?:\s+\w+(?:\s*=\s*(?:"[\s\S]*?"|'[\s\S]*?'|[^'">\s]+))?)+\s*|\s*)>([\s\S]*?)<\/\1>`)
  188. let index = 0
  189. function marking (str) {
  190. index++
  191. return `<mark class="extract" id="mark-${index}">${str}</mark>`
  192. }
  193. this.teiparsed = this.teiparsed.replace(regexp, marking)
  194. },
  195. // parsePageBreaks () {
  196. // let pbs = this.html.match(/<span role="pageBreak"[^>]+><\/span>/g)
  197. // console.log('pagebreaks', pbs)
  198. // if (pbs) {
  199. // let pbparts, newpb, num
  200. // for (var i = 0; i < pbs.length; i++) {
  201. // pbparts = RegExp(/<span role="pageBreak" data-num="(.+)"><\/span>/).exec(pbs[i], 'g')
  202. // if (!pbparts) {
  203. // console.warn(`pageBreak ${i} maformed`, pbs[i])
  204. // } else {
  205. // // console.log('pbparts', pbparts)
  206. // num = pbparts[1]
  207. // this.pages.push(num)
  208. // newpb = `<span` +
  209. // // ` id="page-break-${num}"` +
  210. // ` role="pageBreak"` +
  211. // ` data-num="${num}"` +
  212. // ` data-num-prev="${num - 1}"` +
  213. // ` />`
  214. // // console.log('newpb', newpb)
  215. // this.html = this.html.replace(pbs[i], newpb)
  216. // }
  217. // }
  218. // }
  219. // },
  220. onClickRef (e) {
  221. console.log('onClickRef(e)', e)
  222. if (e.target.classList.contains('tapped')) {
  223. this.$router.push({
  224. name: e.target.dataset.index,
  225. params: { id: e.target.dataset.uuid }
  226. })
  227. }
  228. },
  229. onHoverLink (e) {
  230. console.log('EdText onHoverLink(e)', e)
  231. this.$emit('onHoverLink', {
  232. uuid: e.target.dataset.uuid,
  233. index: e.target.dataset.index,
  234. rect: e.target.getBoundingClientRect()
  235. })
  236. },
  237. onTapLink (e) {
  238. console.log('EdText onTapLink(e)', e)
  239. this.$emit('onHoverLink', {
  240. uuid: e.target.dataset.uuid,
  241. index: e.target.dataset.index,
  242. rect: e.target.getBoundingClientRect()
  243. })
  244. },
  245. onLeaveLink (e) {
  246. // console.log('EdText onLeaveLink(e)', e)
  247. this.$emit('onLeaveLink')
  248. }
  249. // ,
  250. // onClickCopyClipboard (e) {
  251. // e.preventDefault()
  252. // console.log('onClickCopyClipboard', e)
  253. // // navigator.clipboard.writeText(e.target.getAttribute('href'))
  254. // this.$copyText(e.target.getAttribute('href'))
  255. // return false
  256. // }
  257. }
  258. // render (h) {
  259. // // console.log('EdText render()')
  260. // if (!this.template) {
  261. // return h('span', 'Chargement ...')
  262. // } else {
  263. // return this.template.render.call(this)
  264. // }
  265. // }
  266. }
  267. </script>
  268. <style lang="scss" scoped>
  269. </style>