metadata.ts 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import { EditorView } from '@codemirror/view'
  2. import { Transaction, Text } from '@codemirror/state'
  3. const metadataChangeRe = /\\(documentclass|usepackage|RequirePackage|label)\b/
  4. const optionChangeRe = /\b(label)=/
  5. export const metadata = () => [
  6. // trigger metadata reload if edited line contains metadata-related commands
  7. EditorView.updateListener.of(update => {
  8. if (update.docChanged) {
  9. let needsMetadataUpdate = false
  10. for (const transaction of update.transactions) {
  11. // ignore remote changes
  12. if (transaction.annotation(Transaction.remote)) {
  13. continue
  14. }
  15. transaction.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
  16. const docs: [Text, number, number][] = [
  17. [update.startState.doc, fromA, toA],
  18. [update.state.doc, fromB, toB],
  19. ]
  20. for (const [doc, from, to] of docs) {
  21. const fromLine = doc.lineAt(from).number
  22. const toLine = doc.lineAt(to).number
  23. for (const line of doc.iterLines(fromLine, toLine + 1)) {
  24. if (metadataChangeRe.test(line) || optionChangeRe.test(line)) {
  25. needsMetadataUpdate = true
  26. return
  27. }
  28. }
  29. }
  30. })
  31. if (needsMetadataUpdate) {
  32. window.dispatchEvent(new CustomEvent('editor:metadata-outdated'))
  33. break
  34. }
  35. }
  36. }
  37. }),
  38. ]