EdText.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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[1]) {
  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 = `<span class="no-wrap">${items[i]}&nbsp;${icon}</span>`
  111. // newspan = `${items[i]}&nbsp;${icon}`
  112. this.teiparsed = this.teiparsed.replace(items[i], newspan)
  113. }
  114. }
  115. },
  116. parseLinks () {
  117. let links = this.teiparsed.match(/<a[^<]+<\/a>/g)
  118. // console.log('links', links)
  119. if (links) {
  120. // let domparser = new DOMParser()
  121. // let domlink
  122. let linkparts, newlink, uuid
  123. let index = null
  124. for (var i = 0; i < links.length; i++) {
  125. // console.log(`link ${i}:`, links[i])
  126. linkparts = RegExp(/<a class="(.+)" href="(.+)" data-index="(.+)">(.+)<\/a>/g).exec(links[i], 'g')
  127. // console.log('linkparts', linkparts)
  128. if (!linkparts) {
  129. console.warn(`link ${i} malformed:`, links[i])
  130. } else {
  131. index = linkparts[3]
  132. uuid = linkparts[2].replace('#', '')
  133. newlink = `<a` +
  134. ` class="${linkparts[1]} active-link"` +
  135. ` data-index="${index}"` +
  136. ` data-uuid="${uuid}"` +
  137. ` href="/${index}/${uuid}"` +
  138. ` @click.prevent="onClickRef"` +
  139. ` @keyup.enter="onClickRef"` +
  140. ` @mouseover="onHoverLink"` +
  141. ` @mouseleave="onLeaveLink"` +
  142. // prevent click on this one
  143. ` v-touch:tap.prevent="onTapLink"` +
  144. ` v-touch-class="'tapped'"` +
  145. `>${linkparts[4]}` +
  146. // `<sup class="mdi mdi-message-text-outline" />` +
  147. `</a>`
  148. // console.log('newlink', newlink)
  149. this.teiparsed = this.teiparsed.replace(links[i], newlink)
  150. }
  151. }
  152. // console.log('this.html', this.html)
  153. }
  154. },
  155. parseFigures () {
  156. // console.log('parseFigures this.tei', this.teiparsed)
  157. let imgs = this.teiparsed.match(/<img[^>]*>/g)
  158. console.log('imgs', imgs)
  159. if (imgs) {
  160. let imgparts, newsrc, newimg
  161. for (var i = 0; i < imgs.length; i++) {
  162. // console.log(`link ${i}:`, links[i])
  163. imgparts = RegExp(/<img src="(.+)" alt="(.+)">/g).exec(imgs[i], 'g')
  164. console.log('imgparts', imgparts)
  165. if (!imgparts) {
  166. console.warn(`img ${i} malformed:`, imgs[i])
  167. } else {
  168. newsrc = `${imgparts[1]}/full/1000,/0/native.jpg`
  169. newimg = `<img` +
  170. ` src="${newsrc}"` +
  171. ` alt="${imgparts[2]}"` +
  172. `/>`
  173. // console.log('newlink', newlink)
  174. this.teiparsed = this.teiparsed.replace(imgs[i], newimg)
  175. }
  176. }
  177. }
  178. },
  179. parseExtract () {
  180. console.log('Parse extract', this.extractid)
  181. // let regexp = RegExp(this.extract, 'gim')
  182. let regexp = RegExp(`<span[^>]* id="${this.extractid}"[^>]*>[^<]*</span>`)
  183. // let regexp = RegExp(`<(\w+)((?:\s+\w+(?:\s*=\s*(?:"[\s\S]*?"|'[\s\S]*?'|[^'">\s]+))?)+\s*|\s*)>([\s\S]*?)<\/\1>`)
  184. let index = 0
  185. function marking (str) {
  186. index++
  187. return `<mark class="extract" id="mark-${index}">${str}</mark>`
  188. }
  189. this.teiparsed = this.teiparsed.replace(regexp, marking)
  190. },
  191. // parsePageBreaks () {
  192. // let pbs = this.html.match(/<span role="pageBreak"[^>]+><\/span>/g)
  193. // console.log('pagebreaks', pbs)
  194. // if (pbs) {
  195. // let pbparts, newpb, num
  196. // for (var i = 0; i < pbs.length; i++) {
  197. // pbparts = RegExp(/<span role="pageBreak" data-num="(.+)"><\/span>/).exec(pbs[i], 'g')
  198. // if (!pbparts) {
  199. // console.warn(`pageBreak ${i} maformed`, pbs[i])
  200. // } else {
  201. // // console.log('pbparts', pbparts)
  202. // num = pbparts[1]
  203. // this.pages.push(num)
  204. // newpb = `<span` +
  205. // // ` id="page-break-${num}"` +
  206. // ` role="pageBreak"` +
  207. // ` data-num="${num}"` +
  208. // ` data-num-prev="${num - 1}"` +
  209. // ` />`
  210. // // console.log('newpb', newpb)
  211. // this.html = this.html.replace(pbs[i], newpb)
  212. // }
  213. // }
  214. // }
  215. // },
  216. onClickRef (e) {
  217. console.log('onClickRef(e)', e)
  218. if (e.target.classList.contains('tapped')) {
  219. this.$router.push({
  220. name: e.target.dataset.index,
  221. params: { id: e.target.dataset.uuid }
  222. })
  223. }
  224. },
  225. onHoverLink (e) {
  226. console.log('EdText onHoverLink(e)', e)
  227. this.$emit('onHoverLink', {
  228. uuid: e.target.dataset.uuid,
  229. index: e.target.dataset.index,
  230. rect: e.target.getBoundingClientRect()
  231. })
  232. },
  233. onTapLink (e) {
  234. console.log('EdText onTapLink(e)', e)
  235. this.$emit('onHoverLink', {
  236. uuid: e.target.dataset.uuid,
  237. index: e.target.dataset.index,
  238. rect: e.target.getBoundingClientRect()
  239. })
  240. },
  241. onLeaveLink (e) {
  242. // console.log('EdText onLeaveLink(e)', e)
  243. this.$emit('onLeaveLink')
  244. }
  245. // ,
  246. // onClickCopyClipboard (e) {
  247. // e.preventDefault()
  248. // console.log('onClickCopyClipboard', e)
  249. // // navigator.clipboard.writeText(e.target.getAttribute('href'))
  250. // this.$copyText(e.target.getAttribute('href'))
  251. // return false
  252. // }
  253. }
  254. // render (h) {
  255. // // console.log('EdText render()')
  256. // if (!this.template) {
  257. // return h('span', 'Chargement ...')
  258. // } else {
  259. // return this.template.render.call(this)
  260. // }
  261. // }
  262. }
  263. </script>
  264. <style lang="scss" scoped>
  265. </style>