autumnnote 1.15.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +53 -2
  2. package/dist/autumnnote.cjs +21 -21
  3. package/dist/autumnnote.css +1 -1
  4. package/dist/autumnnote.es.js +1470 -5884
  5. package/dist/autumnnote.es.js.map +1 -1
  6. package/dist/autumnnote.min.js +61 -0
  7. package/dist/autumnnote.umd.js +21 -21
  8. package/dist/autumnnote.umd.js.map +1 -1
  9. package/dist/emoji-data-BDQX5kh-.js +2331 -0
  10. package/dist/emoji-data-BDQX5kh-.js.map +1 -0
  11. package/package.json +9 -5
  12. package/src/js/Context.js +216 -17
  13. package/src/js/editing/History.js +38 -6
  14. package/src/js/i18n/all.js +27 -0
  15. package/src/js/i18n/de.js +15 -0
  16. package/src/js/i18n/en.js +15 -0
  17. package/src/js/i18n/es.js +15 -0
  18. package/src/js/i18n/fr.js +15 -0
  19. package/src/js/i18n/index.js +45 -19
  20. package/src/js/i18n/ja.js +15 -0
  21. package/src/js/i18n/ko.js +15 -0
  22. package/src/js/i18n/vi.js +15 -0
  23. package/src/js/i18n/zh.js +15 -0
  24. package/src/js/index.js +24 -2
  25. package/src/js/index.umd.js +5 -0
  26. package/src/js/module/BaseMediaTooltip.js +142 -0
  27. package/src/js/module/BaseResizer.js +312 -0
  28. package/src/js/module/Clipboard.js +20 -6
  29. package/src/js/module/Editor.js +15 -1
  30. package/src/js/module/EmojiDialog.js +41 -494
  31. package/src/js/module/ImageDialog.js +34 -6
  32. package/src/js/module/ImageResizer.js +23 -241
  33. package/src/js/module/ImageTooltip.js +16 -111
  34. package/src/js/module/MarkdownShortcuts.js +2 -2
  35. package/src/js/module/SlashMenu.js +376 -0
  36. package/src/js/module/Statusbar.js +3 -9
  37. package/src/js/module/VideoResizer.js +38 -239
  38. package/src/js/module/VideoTooltip.js +27 -114
  39. package/src/js/module/emoji-data.js +496 -0
  40. package/src/js/settings.js +27 -0
  41. package/src/styles/autumnnote.scss +49 -0
  42. package/types/i18n/all.d.ts +14 -0
  43. package/types/i18n/de.d.ts +4 -0
  44. package/types/i18n/en.d.ts +4 -0
  45. package/types/i18n/es.d.ts +4 -0
  46. package/types/i18n/fr.d.ts +4 -0
  47. package/types/i18n/ja.d.ts +4 -0
  48. package/types/i18n/ko.d.ts +4 -0
  49. package/types/i18n/vi.d.ts +4 -0
  50. package/types/i18n/zh.d.ts +4 -0
  51. package/types/index.d.ts +113 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emoji-data-BDQX5kh-.js","names":[],"sources":["../src/js/module/emoji-data.js"],"sourcesContent":["/**\n * emoji-data.js — Emoji catalogue for EmojiDialog.\n *\n * Kept in its own module and pulled in with a dynamic import so the ~25 KB\n * table (≈6 KB gzip) becomes a separate chunk instead of riding along in the\n * main bundle for every consumer, including those whose toolbar has no emoji\n * button. The UMD/CDN build inlines it again, since script tags cannot fetch\n * chunks.\n */\n\nexport const EMOJI_CATS = [\n { id: 'smileys', label: 'Smileys' },\n { id: 'people', label: 'People' },\n { id: 'animals', label: 'Animals' },\n { id: 'food', label: 'Food' },\n { id: 'travel', label: 'Travel' },\n { id: 'objects', label: 'Objects' },\n { id: 'symbols', label: 'Symbols' },\n];\n\n// [emoji_char, search_keywords, category]\nexport const EMOJI_LIST = [\n // Smileys & Emotions\n ['😀', 'grin smile happy face', 'smileys'],\n ['😃', 'happy smile big eyes', 'smileys'],\n ['😄', 'grinning smile laugh', 'smileys'],\n ['😁', 'beaming smile grin', 'smileys'],\n ['😆', 'laughing lol', 'smileys'],\n ['😅', 'sweat grin awkward', 'smileys'],\n ['🤣', 'rolling laugh rofl', 'smileys'],\n ['😂', 'tears laugh cry joy', 'smileys'],\n ['🙂', 'slight smile', 'smileys'],\n ['🙃', 'upside down smile', 'smileys'],\n ['😉', 'wink', 'smileys'],\n ['😊', 'blush smile happy', 'smileys'],\n ['😇', 'innocent halo angel', 'smileys'],\n ['🥰', 'hearts love adore', 'smileys'],\n ['😍', 'heart eyes love', 'smileys'],\n ['🤩', 'star eyes excited wow', 'smileys'],\n ['😘', 'kiss blow love', 'smileys'],\n ['😋', 'yum delicious tongue', 'smileys'],\n ['😛', 'tongue stuck out', 'smileys'],\n ['😜', 'wink tongue crazy', 'smileys'],\n ['🤪', 'zany crazy wild', 'smileys'],\n ['😝', 'squint tongue', 'smileys'],\n ['🤑', 'money mouth', 'smileys'],\n ['🤗', 'hugging hug', 'smileys'],\n ['🤔', 'thinking hmm', 'smileys'],\n ['🤨', 'raised eyebrow', 'smileys'],\n ['😐', 'neutral face', 'smileys'],\n ['😶', 'no mouth', 'smileys'],\n ['😏', 'smirk', 'smileys'],\n ['😒', 'unamused', 'smileys'],\n ['🙄', 'roll eyes', 'smileys'],\n ['😬', 'grimace', 'smileys'],\n ['😔', 'pensive sad', 'smileys'],\n ['😪', 'sleepy tired', 'smileys'],\n ['😴', 'sleeping zzz', 'smileys'],\n ['🤤', 'drool', 'smileys'],\n ['😷', 'mask sick', 'smileys'],\n ['🤒', 'sick thermometer', 'smileys'],\n ['🤕', 'hurt bandage', 'smileys'],\n ['🤢', 'nausea sick', 'smileys'],\n ['🤮', 'vomit sick', 'smileys'],\n ['🤧', 'sneeze cold', 'smileys'],\n ['🥵', 'hot sweat', 'smileys'],\n ['🥶', 'cold freeze', 'smileys'],\n ['😵', 'dizzy dead', 'smileys'],\n ['🤯', 'mind blown', 'smileys'],\n ['🤠', 'cowboy hat', 'smileys'],\n ['🥳', 'party celebrate', 'smileys'],\n ['😎', 'cool sunglasses', 'smileys'],\n ['🤓', 'nerd glasses', 'smileys'],\n ['🧐', 'monocle curious', 'smileys'],\n ['😕', 'confused', 'smileys'],\n ['😟', 'worried', 'smileys'],\n ['🙁', 'frown sad', 'smileys'],\n ['☹️', 'sad frown', 'smileys'],\n ['😮', 'surprised open mouth', 'smileys'],\n ['😲', 'astonished', 'smileys'],\n ['🥺', 'pleading begging puppy eyes', 'smileys'],\n ['😢', 'cry sad tear', 'smileys'],\n ['😭', 'sob cry loudly', 'smileys'],\n ['😱', 'scream horror fear', 'smileys'],\n ['😡', 'angry red pouting', 'smileys'],\n ['😠', 'angry mad', 'smileys'],\n ['🤬', 'cursing swear', 'smileys'],\n ['😈', 'devil evil smile', 'smileys'],\n ['👿', 'devil angry evil', 'smileys'],\n ['💀', 'skull death', 'smileys'],\n ['☠️', 'skull crossbones', 'smileys'],\n ['💩', 'poop', 'smileys'],\n ['🤡', 'clown', 'smileys'],\n ['👻', 'ghost boo', 'smileys'],\n ['👽', 'alien ufo', 'smileys'],\n ['🤖', 'robot', 'smileys'],\n\n // People & Body\n ['👋', 'wave hello hi hand', 'people'],\n ['🤚', 'raised back hand', 'people'],\n ['✋', 'raised hand stop', 'people'],\n ['🖖', 'vulcan salute spock', 'people'],\n ['👌', 'ok perfect fine', 'people'],\n ['✌️', 'peace victory fingers', 'people'],\n ['🤞', 'fingers crossed luck', 'people'],\n ['🤟', 'love you gesture', 'people'],\n ['🤘', 'sign of horns rock', 'people'],\n ['🤙', 'call me hand', 'people'],\n ['👈', 'point left', 'people'],\n ['👉', 'point right', 'people'],\n ['👆', 'point up', 'people'],\n ['👇', 'point down', 'people'],\n ['☝️', 'index pointing up', 'people'],\n ['👍', 'thumbs up like good', 'people'],\n ['👎', 'thumbs down dislike bad', 'people'],\n ['✊', 'raised fist punch', 'people'],\n ['👊', 'oncoming fist punch', 'people'],\n ['👏', 'clap applause', 'people'],\n ['🙌', 'celebrate raise hands', 'people'],\n ['🤝', 'handshake deal', 'people'],\n ['🙏', 'pray hope please thanks', 'people'],\n ['💅', 'nail polish', 'people'],\n ['💪', 'flexed bicep strong muscle', 'people'],\n ['👀', 'eyes look see', 'people'],\n ['👁️', 'eye', 'people'],\n ['👅', 'tongue', 'people'],\n ['👶', 'baby', 'people'],\n ['🧒', 'child', 'people'],\n ['👦', 'boy', 'people'],\n ['👧', 'girl', 'people'],\n ['🧑', 'person adult', 'people'],\n ['👨', 'man', 'people'],\n ['👩', 'woman', 'people'],\n ['🧔', 'beard man', 'people'],\n ['🧓', 'older person', 'people'],\n ['👴', 'old man', 'people'],\n ['👵', 'old woman', 'people'],\n ['❤️', 'heart love red', 'people'],\n ['🧡', 'orange heart love', 'people'],\n ['💛', 'yellow heart love', 'people'],\n ['💚', 'green heart love', 'people'],\n ['💙', 'blue heart love', 'people'],\n ['💜', 'purple heart love', 'people'],\n ['🖤', 'black heart', 'people'],\n ['🤍', 'white heart', 'people'],\n ['🤎', 'brown heart', 'people'],\n ['💔', 'broken heart', 'people'],\n ['❣️', 'exclamation heart', 'people'],\n ['💕', 'two hearts love', 'people'],\n ['💞', 'revolving hearts', 'people'],\n ['💓', 'beating heart', 'people'],\n ['💗', 'growing heart', 'people'],\n ['💖', 'sparkling heart', 'people'],\n ['💘', 'heart arrow', 'people'],\n ['💝', 'heart ribbon', 'people'],\n ['💬', 'speech bubble comment chat', 'people'],\n ['💭', 'thought bubble', 'people'],\n ['💯', '100 hundred percent perfect', 'people'],\n ['💢', 'anger symbol mad', 'people'],\n ['💤', 'zzz sleep', 'people'],\n\n // Animals & Nature\n ['🐶', 'dog puppy', 'animals'],\n ['🐱', 'cat kitten', 'animals'],\n ['🐭', 'mouse', 'animals'],\n ['🐹', 'hamster', 'animals'],\n ['🐰', 'rabbit bunny', 'animals'],\n ['🦊', 'fox', 'animals'],\n ['🐻', 'bear', 'animals'],\n ['🐼', 'panda', 'animals'],\n ['🐨', 'koala', 'animals'],\n ['🐯', 'tiger', 'animals'],\n ['🦁', 'lion', 'animals'],\n ['🐮', 'cow', 'animals'],\n ['🐷', 'pig', 'animals'],\n ['🐸', 'frog', 'animals'],\n ['🐵', 'monkey', 'animals'],\n ['🙈', 'see no evil monkey', 'animals'],\n ['🙉', 'hear no evil monkey', 'animals'],\n ['🙊', 'speak no evil monkey', 'animals'],\n ['🐔', 'chicken hen', 'animals'],\n ['🐧', 'penguin', 'animals'],\n ['🐦', 'bird', 'animals'],\n ['🦆', 'duck', 'animals'],\n ['🦅', 'eagle', 'animals'],\n ['🦉', 'owl', 'animals'],\n ['🦇', 'bat', 'animals'],\n ['🐺', 'wolf', 'animals'],\n ['🐴', 'horse', 'animals'],\n ['🦄', 'unicorn', 'animals'],\n ['🐝', 'bee', 'animals'],\n ['🦋', 'butterfly', 'animals'],\n ['🐌', 'snail', 'animals'],\n ['🐞', 'ladybug', 'animals'],\n ['🐢', 'turtle', 'animals'],\n ['🐍', 'snake', 'animals'],\n ['🦎', 'lizard', 'animals'],\n ['🐊', 'crocodile', 'animals'],\n ['🐟', 'fish', 'animals'],\n ['🐠', 'tropical fish', 'animals'],\n ['🦈', 'shark', 'animals'],\n ['🐬', 'dolphin', 'animals'],\n ['🐳', 'whale', 'animals'],\n ['🐙', 'octopus', 'animals'],\n ['🦑', 'squid', 'animals'],\n ['🦀', 'crab', 'animals'],\n ['🌸', 'cherry blossom flower', 'animals'],\n ['🌺', 'hibiscus flower', 'animals'],\n ['🌻', 'sunflower', 'animals'],\n ['🌹', 'rose flower', 'animals'],\n ['🌷', 'tulip flower', 'animals'],\n ['🍀', 'four leaf clover luck', 'animals'],\n ['🌿', 'herb leaf green', 'animals'],\n ['🌱', 'seedling sprout', 'animals'],\n ['🌲', 'evergreen tree pine', 'animals'],\n ['🌳', 'deciduous tree', 'animals'],\n ['🌴', 'palm tree', 'animals'],\n ['🍄', 'mushroom', 'animals'],\n ['🌾', 'sheaf wheat', 'animals'],\n ['🐾', 'paw prints animal', 'animals'],\n\n // Food & Drink\n ['🍎', 'apple red', 'food'],\n ['🍊', 'orange tangerine', 'food'],\n ['🍋', 'lemon yellow', 'food'],\n ['🍇', 'grapes', 'food'],\n ['🍓', 'strawberry', 'food'],\n ['🫐', 'blueberry', 'food'],\n ['🍒', 'cherry', 'food'],\n ['🍑', 'peach', 'food'],\n ['🥭', 'mango', 'food'],\n ['🍍', 'pineapple', 'food'],\n ['🥥', 'coconut', 'food'],\n ['🥝', 'kiwi', 'food'],\n ['🍅', 'tomato', 'food'],\n ['🥑', 'avocado', 'food'],\n ['🍆', 'eggplant aubergine', 'food'],\n ['🥕', 'carrot', 'food'],\n ['🌽', 'corn', 'food'],\n ['🥦', 'broccoli', 'food'],\n ['🥬', 'leafy green', 'food'],\n ['🧄', 'garlic', 'food'],\n ['🥜', 'peanut nut', 'food'],\n ['🍞', 'bread loaf', 'food'],\n ['🥐', 'croissant', 'food'],\n ['🧀', 'cheese', 'food'],\n ['🍳', 'egg fry cooking', 'food'],\n ['🥚', 'egg', 'food'],\n ['🥞', 'pancake', 'food'],\n ['🧇', 'waffle', 'food'],\n ['🥓', 'bacon', 'food'],\n ['🥩', 'meat steak', 'food'],\n ['🍗', 'chicken leg', 'food'],\n ['🌭', 'hotdog', 'food'],\n ['🍔', 'burger hamburger', 'food'],\n ['🍟', 'fries french', 'food'],\n ['🍕', 'pizza', 'food'],\n ['🌮', 'taco', 'food'],\n ['🌯', 'burrito wrap', 'food'],\n ['🍜', 'noodles ramen', 'food'],\n ['🍝', 'spaghetti pasta', 'food'],\n ['🍣', 'sushi', 'food'],\n ['🍱', 'bento box', 'food'],\n ['🍦', 'ice cream soft serve', 'food'],\n ['🍩', 'donut', 'food'],\n ['🍪', 'cookie', 'food'],\n ['🎂', 'birthday cake', 'food'],\n ['🍰', 'cake slice', 'food'],\n ['🧁', 'cupcake', 'food'],\n ['🍫', 'chocolate', 'food'],\n ['🍬', 'candy', 'food'],\n ['🍭', 'lollipop', 'food'],\n ['☕', 'coffee hot', 'food'],\n ['🍵', 'tea hot', 'food'],\n ['🧋', 'bubble tea boba', 'food'],\n ['🥤', 'cup straw drink', 'food'],\n ['🍷', 'wine red', 'food'],\n ['🍸', 'cocktail martini', 'food'],\n ['🍺', 'beer mug', 'food'],\n ['🍻', 'clinking beer mugs', 'food'],\n ['🥂', 'champagne toast celebrate', 'food'],\n ['🧃', 'juice box', 'food'],\n ['🧊', 'ice cube', 'food'],\n\n // Travel & Places\n ['🚀', 'rocket space', 'travel'],\n ['🛸', 'ufo flying saucer', 'travel'],\n ['✈️', 'airplane plane fly', 'travel'],\n ['🚁', 'helicopter', 'travel'],\n ['🚂', 'train locomotive', 'travel'],\n ['🚄', 'bullet train fast', 'travel'],\n ['🚇', 'subway metro', 'travel'],\n ['🚌', 'bus', 'travel'],\n ['🚑', 'ambulance', 'travel'],\n ['🚒', 'fire truck', 'travel'],\n ['🚓', 'police car', 'travel'],\n ['🚕', 'taxi cab', 'travel'],\n ['🚗', 'car automobile red', 'travel'],\n ['🚙', 'suv car', 'travel'],\n ['🚚', 'truck delivery', 'travel'],\n ['🚜', 'tractor farm', 'travel'],\n ['🏎️', 'racing car fast', 'travel'],\n ['🏍️', 'motorcycle', 'travel'],\n ['🚲', 'bicycle bike', 'travel'],\n ['🛴', 'scooter kick', 'travel'],\n ['⛵', 'sailboat boat', 'travel'],\n ['🚢', 'ship cruise', 'travel'],\n ['🏠', 'house home', 'travel'],\n ['🏢', 'office building', 'travel'],\n ['🏥', 'hospital', 'travel'],\n ['🏦', 'bank', 'travel'],\n ['🏪', 'store shop convenience', 'travel'],\n ['🏫', 'school', 'travel'],\n ['🏰', 'castle european', 'travel'],\n ['🏯', 'japanese castle', 'travel'],\n ['🗼', 'tokyo tower', 'travel'],\n ['🗽', 'statue liberty new york', 'travel'],\n ['⛪', 'church', 'travel'],\n ['🕌', 'mosque', 'travel'],\n ['⛩️', 'shinto shrine', 'travel'],\n ['⛲', 'fountain', 'travel'],\n ['⛺', 'tent camping', 'travel'],\n ['🌁', 'fog foggy bridge', 'travel'],\n ['🌃', 'night city stars', 'travel'],\n ['🏙️', 'cityscape city buildings', 'travel'],\n ['🌅', 'sunrise morning', 'travel'],\n ['🌈', 'rainbow colorful', 'travel'],\n ['⛰️', 'mountain', 'travel'],\n ['🏔️', 'snow mountain', 'travel'],\n ['🗻', 'mount fuji', 'travel'],\n ['🏕️', 'camping tent', 'travel'],\n ['🗺️', 'world map', 'travel'],\n ['🧭', 'compass navigation', 'travel'],\n ['🌍', 'earth europe africa globe', 'travel'],\n ['🌎', 'earth americas globe', 'travel'],\n ['🌏', 'earth asia globe', 'travel'],\n ['🌐', 'globe internet web', 'travel'],\n\n // Objects\n ['💎', 'diamond gem jewel', 'objects'],\n ['💍', 'ring engagement', 'objects'],\n ['👑', 'crown royal king queen', 'objects'],\n ['🎩', 'top hat magic', 'objects'],\n ['💼', 'briefcase work business', 'objects'],\n ['👜', 'handbag purse', 'objects'],\n ['🎒', 'backpack bag school', 'objects'],\n ['👓', 'glasses eyewear', 'objects'],\n ['🕶️', 'sunglasses cool', 'objects'],\n ['💡', 'light bulb idea', 'objects'],\n ['🔦', 'flashlight torch', 'objects'],\n ['🕯️', 'candle light', 'objects'],\n ['🔋', 'battery charge', 'objects'],\n ['💻', 'laptop computer', 'objects'],\n ['🖥️', 'desktop monitor computer', 'objects'],\n ['📱', 'phone mobile cell', 'objects'],\n ['⌨️', 'keyboard type', 'objects'],\n ['🖱️', 'mouse computer click', 'objects'],\n ['📺', 'television tv', 'objects'],\n ['📷', 'camera photo', 'objects'],\n ['📹', 'video camera', 'objects'],\n ['🎥', 'movie camera film', 'objects'],\n ['☎️', 'telephone phone', 'objects'],\n ['⏰', 'alarm clock wake', 'objects'],\n ['⌚', 'watch time', 'objects'],\n ['🔑', 'key', 'objects'],\n ['🗝️', 'old key', 'objects'],\n ['🔒', 'lock closed', 'objects'],\n ['🔓', 'unlock open', 'objects'],\n ['🔨', 'hammer tool', 'objects'],\n ['🔧', 'wrench tool', 'objects'],\n ['🔩', 'bolt nut', 'objects'],\n ['⚙️', 'gear setting', 'objects'],\n ['🧲', 'magnet attract', 'objects'],\n ['📚', 'books stack library', 'objects'],\n ['📖', 'book open read', 'objects'],\n ['📝', 'memo write note', 'objects'],\n ['✏️', 'pencil write edit', 'objects'],\n ['📌', 'pushpin tack', 'objects'],\n ['📎', 'paperclip attach', 'objects'],\n ['📊', 'bar chart graph', 'objects'],\n ['📈', 'chart up growth trend', 'objects'],\n ['📉', 'chart down loss decline', 'objects'],\n ['📅', 'calendar date', 'objects'],\n ['📦', 'package box', 'objects'],\n ['📫', 'mailbox closed', 'objects'],\n ['📧', 'email envelope', 'objects'],\n ['🎁', 'gift present', 'objects'],\n ['🎀', 'ribbon bow', 'objects'],\n ['🎉', 'party celebrate confetti', 'objects'],\n ['🎊', 'confetti celebrate', 'objects'],\n ['🔮', 'crystal ball magic fortune', 'objects'],\n ['🪄', 'magic wand', 'objects'],\n ['🎯', 'target bullseye dart', 'objects'],\n ['🎲', 'dice game board', 'objects'],\n ['🎮', 'video game controller', 'objects'],\n ['🎭', 'theater masks drama', 'objects'],\n ['🎨', 'art palette paint', 'objects'],\n ['🎬', 'clapper film movie', 'objects'],\n ['🎤', 'microphone sing karaoke', 'objects'],\n ['🎧', 'headphones music listen', 'objects'],\n ['🎵', 'music note', 'objects'],\n ['🎶', 'music notes', 'objects'],\n ['🎸', 'guitar electric', 'objects'],\n ['🎹', 'piano keyboard music', 'objects'],\n ['🥁', 'drum percussion', 'objects'],\n ['🎷', 'saxophone jazz', 'objects'],\n ['🎺', 'trumpet', 'objects'],\n ['🎻', 'violin', 'objects'],\n ['⚽', 'soccer ball football', 'objects'],\n ['🏀', 'basketball', 'objects'],\n ['🏈', 'american football', 'objects'],\n ['⚾', 'baseball', 'objects'],\n ['🎾', 'tennis', 'objects'],\n ['🏐', 'volleyball', 'objects'],\n ['🏆', 'trophy winner award', 'objects'],\n ['🥇', 'gold medal first', 'objects'],\n ['🏅', 'sports medal', 'objects'],\n\n // Symbols\n ['✅', 'check green done success', 'symbols'],\n ['❌', 'cross x no cancel', 'symbols'],\n ['⭕', 'circle red', 'symbols'],\n ['⛔', 'no entry stop', 'symbols'],\n ['🚫', 'prohibited no banned', 'symbols'],\n ['⚠️', 'warning caution danger', 'symbols'],\n ['❗', 'exclamation red important', 'symbols'],\n ['❓', 'question mark', 'symbols'],\n ['‼️', 'double exclamation', 'symbols'],\n ['💯', '100 hundred percent perfect', 'symbols'],\n ['🔴', 'red circle dot', 'symbols'],\n ['🟠', 'orange circle', 'symbols'],\n ['🟡', 'yellow circle', 'symbols'],\n ['🟢', 'green circle', 'symbols'],\n ['🔵', 'blue circle', 'symbols'],\n ['🟣', 'purple circle', 'symbols'],\n ['⚫', 'black circle', 'symbols'],\n ['⚪', 'white circle', 'symbols'],\n ['🟤', 'brown circle', 'symbols'],\n ['🔺', 'red triangle up', 'symbols'],\n ['🔻', 'red triangle down', 'symbols'],\n ['🔷', 'blue diamond large', 'symbols'],\n ['🔶', 'orange diamond large', 'symbols'],\n ['🔹', 'blue diamond small', 'symbols'],\n ['🔸', 'orange diamond small', 'symbols'],\n ['⭐', 'star yellow', 'symbols'],\n ['🌟', 'glowing star shine', 'symbols'],\n ['✨', 'sparkles shine', 'symbols'],\n ['💫', 'dizzy star spin', 'symbols'],\n ['⚡', 'lightning bolt energy power', 'symbols'],\n ['🔥', 'fire hot flame', 'symbols'],\n ['💥', 'explosion boom', 'symbols'],\n ['❄️', 'snowflake cold ice winter', 'symbols'],\n ['🌊', 'wave water ocean sea', 'symbols'],\n ['💨', 'wind blow dash', 'symbols'],\n ['🌀', 'cyclone tornado spiral', 'symbols'],\n ['♻️', 'recycle loop green', 'symbols'],\n ['✔️', 'check tick done', 'symbols'],\n ['➕', 'plus add', 'symbols'],\n ['➖', 'minus subtract', 'symbols'],\n ['➗', 'divide division', 'symbols'],\n ['✖️', 'multiply times cross', 'symbols'],\n ['▶️', 'play button right', 'symbols'],\n ['⏸️', 'pause', 'symbols'],\n ['⏹️', 'stop square', 'symbols'],\n ['⏩', 'fast forward', 'symbols'],\n ['⏪', 'rewind fast backward', 'symbols'],\n ['🔔', 'bell notification', 'symbols'],\n ['🔕', 'bell slash mute', 'symbols'],\n ['🔊', 'speaker volume high', 'symbols'],\n ['🔇', 'mute silent no sound', 'symbols'],\n ['📢', 'loudspeaker announcement', 'symbols'],\n ['📣', 'megaphone cheer', 'symbols'],\n ['🏳️', 'white flag', 'symbols'],\n ['🏴', 'black flag', 'symbols'],\n ['🚩', 'red flag', 'symbols'],\n ['🏁', 'checkered flag finish race', 'symbols'],\n ['🆕', 'new badge', 'symbols'],\n ['🆓', 'free badge', 'symbols'],\n ['🆒', 'cool badge', 'symbols'],\n ['🔝', 'top arrow', 'symbols'],\n ['🔙', 'back arrow', 'symbols'],\n ['ℹ️', 'information info', 'symbols'],\n ['📍', 'pin location map', 'symbols'],\n ['🔗', 'link chain', 'symbols'],\n ['©️', 'copyright', 'symbols'],\n ['®️', 'registered trademark', 'symbols'],\n ['™️', 'trademark', 'symbols'],\n ['#️⃣', 'hash number', 'symbols'],\n ['0️⃣', 'zero number', 'symbols'],\n ['1️⃣', 'one number', 'symbols'],\n ['2️⃣', 'two number', 'symbols'],\n ['3️⃣', 'three number', 'symbols'],\n ['4️⃣', 'four number', 'symbols'],\n ['5️⃣', 'five number', 'symbols'],\n];\n\n"],"mappings":"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AkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAK;EAAkC;CAAQ;CAChD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAO;EAAiC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAiC;CAAQ;CAChD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CAGjD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAkC;CAAS;CAGlD;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAK;EAAkC;CAAM;CAC9C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAC/C;EAAC;EAAM;EAAkC;CAAM;CAG/C;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAO;EAAkC;CAAQ;CAClD;EAAC;EAAO;EAAkC;CAAQ;CAClD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAK;EAAkC;CAAQ;CAChD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAK;EAAkC;CAAQ;CAChD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAK;EAAkC;CAAQ;CAChD;EAAC;EAAK;EAAkC;CAAQ;CAChD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAO;EAAkC;CAAQ;CAClD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAO;EAAkC;CAAQ;CAClD;EAAC;EAAM;EAAkC;CAAQ;CACjD;EAAC;EAAO;EAAkC;CAAQ;CAClD;EAAC;EAAO;EAAkC;CAAQ;CAClD;EAAC;EAAM;EAAkC;CA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;CAAS;CACjD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAM;EAAkC;CAAS;CAClD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAK;EAAiC;CAAS;CAChD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAO;EAAiC;CAAS;CAClD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAM;EAAiC;CAAS;CACjD;EAAC;EAAO;EAAgC;CAAS;CACjD;EAAC;EAAO;EAAgC;CAAS;CACjD;EAAC;EAAO;EAAgC;CAAS;CACjD;EAAC;EAAO;EAAgC;CAAS;CACjD;EAAC;EAAO;EAAgC;CAAS;CACjD;EAAC;EAAO;EAAgC;CAAS;CACjD;EAAC;EAAO;EAAgC;CAAS;CACjD;EAAC;EAAO;EAAgC;CAAS;CACjD;EAAC;EAAO;EAAgC;CAAS;CACjD;EAAC;EAAO;EAAgC;CAAS;AACnD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autumnnote",
3
- "version": "1.15.0",
3
+ "version": "2.0.0",
4
4
  "description": "WYSIWYG rich-text editor built with vanilla JavaScript — zero dependencies, no jQuery. Dark mode, @mention, markdown shortcuts, bubble toolbar. React and Vue 3 wrappers included.",
5
5
  "type": "module",
6
6
  "main": "dist/autumnnote.cjs",
@@ -13,6 +13,10 @@
13
13
  "import": "./dist/autumnnote.es.js",
14
14
  "require": "./dist/autumnnote.cjs"
15
15
  },
16
+ "./i18n/*": {
17
+ "types": "./types/i18n/*.d.ts",
18
+ "import": "./src/js/i18n/*.js"
19
+ },
16
20
  "./dist/autumnnote.css": "./dist/autumnnote.css"
17
21
  },
18
22
  "files": [
@@ -22,7 +26,7 @@
22
26
  ],
23
27
  "scripts": {
24
28
  "dev": "vite",
25
- "build": "vite build && vite build --config vite.umd.config.js && node scripts/create-cjs-alias.mjs",
29
+ "build": "vite build && vite build --config vite.umd.config.js && vite build --config vite.cdn.config.js && node scripts/create-cjs-alias.mjs",
26
30
  "build:demo": "vite build --config vite.demo.config.js",
27
31
  "preview": "vite preview",
28
32
  "prepublishOnly": "npm run build",
@@ -100,13 +104,13 @@
100
104
  "@vitest/browser-playwright": "^4.1.10",
101
105
  "@vitest/coverage-v8": "^4.1.8",
102
106
  "cross-env": "^10.1.0",
103
- "eslint": "10.3.0",
107
+ "eslint": "10.7.0",
104
108
  "jsdom": "^25.0.1",
105
109
  "playwright": "^1.61.1",
106
110
  "rollup-plugin-visualizer": "^7.0.1",
107
- "sass": "^1.99.0",
111
+ "sass": "^1.101.0",
108
112
  "typescript": "^6.0.2",
109
- "vite": "^8.0.16",
113
+ "vite": "^8.1.5",
110
114
  "vitest": "^4.1.8"
111
115
  },
112
116
  "packageManager": "pnpm@11.1.3",
package/src/js/Context.js CHANGED
@@ -39,10 +39,26 @@ import { AutoSaveRestore } from './module/AutoSaveRestore.js';
39
39
  import { MarkdownShortcuts } from './module/MarkdownShortcuts.js';
40
40
  import { BubbleToolbar } from './module/BubbleToolbar.js';
41
41
  import { Mention } from './module/Mention.js';
42
+ import { SlashMenu } from './module/SlashMenu.js';
42
43
 
43
44
  /** Module registry shared across all Context instances (populated via AutumnNote.registerModule). */
44
45
  export const _customModules = new Map();
45
46
 
47
+ /**
48
+ * Modules whose registration depends on an option value. Declared once so the
49
+ * initial mount (`_registerModules`) and runtime toggles (`updateOptions`) can
50
+ * never drift apart — previously `updateOptions({ bubbleToolbar: true })`
51
+ * changed the option but silently left the module unregistered.
52
+ * @type {Array<{ name: string, Class: new (ctx: Context) => { initialize: () => any, destroy?: () => void }, enabled: (options: any) => boolean }>}
53
+ */
54
+ const OPTIONAL_MODULES = [
55
+ { name: 'autoSaveRestore', Class: AutoSaveRestore, enabled: (o) => !!o.autoSaveRestore },
56
+ { name: 'markdownShortcuts', Class: MarkdownShortcuts, enabled: (o) => o.markdownShortcuts !== false },
57
+ { name: 'bubbleToolbar', Class: BubbleToolbar, enabled: (o) => !!o.bubbleToolbar },
58
+ { name: 'mention', Class: Mention, enabled: (o) => !!o.mention },
59
+ { name: 'slashMenu', Class: SlashMenu, enabled: (o) => o.slashMenu !== false },
60
+ ];
61
+
46
62
  /** Global plugin registry (populated via AutumnNote.use()). Applied to every new Context. */
47
63
  export const _globalPlugins = new Map();
48
64
 
@@ -72,6 +88,11 @@ export class Context {
72
88
 
73
89
  this._disposers = [];
74
90
  this._alive = false;
91
+ this._autoSaveTimer = null;
92
+ this._pendingAutoSave = null;
93
+ this._suppressedRemoteHTML = null;
94
+ /** @type {Promise<void>|null} Settles when destroy()'s closing auto-save finishes */
95
+ this._destroyPromise = null;
75
96
  }
76
97
 
77
98
  // ---------------------------------------------------------------------------
@@ -153,10 +174,9 @@ export class Context {
153
174
  register('shortcutsDialog', ShortcutsDialog);
154
175
  register('findReplace', FindReplace);
155
176
  register('imageCropOverlay', ImageCropOverlay);
156
- register('autoSaveRestore', AutoSaveRestore);
157
- register('markdownShortcuts', MarkdownShortcuts);
158
- register('bubbleToolbar', BubbleToolbar);
159
- register('mention', Mention);
177
+ for (const { name, Class, enabled } of OPTIONAL_MODULES) {
178
+ if (enabled(this.options)) register(name, Class);
179
+ }
160
180
 
161
181
  // Custom modules registered via AutumnNote.registerModule()
162
182
  if (_customModules.size > 0) {
@@ -166,6 +186,29 @@ export class Context {
166
186
  }
167
187
  }
168
188
 
189
+ /**
190
+ * Registers or tears down option-gated modules so they match the current
191
+ * option values. Called after `updateOptions()` so toggling e.g.
192
+ * `bubbleToolbar` at runtime actually takes effect.
193
+ */
194
+ _syncOptionalModules() {
195
+ for (const { name, Class, enabled } of OPTIONAL_MODULES) {
196
+ const shouldRun = enabled(this.options);
197
+ const isRunning = this._modules.has(name);
198
+ if (shouldRun === isRunning) continue;
199
+
200
+ if (shouldRun) {
201
+ const instance = new Class(this);
202
+ this._modules.set(name, instance);
203
+ instance.initialize();
204
+ } else {
205
+ const instance = this._modules.get(name);
206
+ if (typeof instance?.destroy === 'function') instance.destroy();
207
+ this._modules.delete(name);
208
+ }
209
+ }
210
+ }
211
+
169
212
  /**
170
213
  * Registers and initialises a custom module on this instance.
171
214
  * @param {string} name
@@ -180,6 +223,18 @@ export class Context {
180
223
  return this;
181
224
  }
182
225
 
226
+ registerSlashCommand(command) {
227
+ if (!command?.id || typeof command.run !== 'function') {
228
+ throw new TypeError('[AutumnNote] Slash command requires an id and run(context) function.');
229
+ }
230
+ const commands = this.options.slashCommands || (this.options.slashCommands = []);
231
+ const index = commands.findIndex((item) => item.id === command.id);
232
+ if (index >= 0) commands[index] = command;
233
+ else commands.push(command);
234
+ this.invoke('slashMenu.refresh');
235
+ return this;
236
+ }
237
+
183
238
  /**
184
239
  * Installs a plugin on this editor instance.
185
240
  * If called after create(), buttons are registered immediately but the toolbar
@@ -246,22 +301,57 @@ export class Context {
246
301
  }
247
302
  });
248
303
  // Sync textarea/input value on every change so form.submit() always gets fresh content
249
- const d3 = this.on('change', () => this._syncToTarget());
250
- this._disposers.push(d0, d1, d2, d3);
304
+ const d3 = this.on('change', (html) => this._syncToTarget(html));
305
+ const dRemote = this.on('change', (html) => {
306
+ if (this.options.blockIds) { this.ensureBlockIds(); html = this.getHTML(); }
307
+ if (html === this._suppressedRemoteHTML) { this._suppressedRemoteHTML = null; return; }
308
+ this.options.collaborationAdapter?.onLocalChange?.(html, this);
309
+ });
310
+ this._disposers.push(d0, d1, d2, d3, dRemote);
251
311
 
252
312
  // Auto-save to localStorage on every change (also writes :asrmeta for restore banner)
253
313
  if (this.options.autoSave && this.options.autoSaveKey) {
254
- const d4 = this.on('change', () => {
255
- try {
256
- const key = this.options.autoSaveKey;
257
- localStorage.setItem(key, this.getHTML());
258
- localStorage.setItem(key + ':asrmeta', JSON.stringify({ savedAt: Date.now() }));
259
- } catch (_) { void _; }
260
- });
314
+ const d4 = this.on('change', (html) => this._scheduleAutoSave(html));
261
315
  this._disposers.push(d4);
262
316
  }
263
317
  }
264
318
 
319
+ _scheduleAutoSave(html) {
320
+ this._pendingAutoSave = html;
321
+ clearTimeout(this._autoSaveTimer);
322
+ this._autoSaveTimer = setTimeout(() => this.flushAutoSave(), this.options.autoSaveDelay ?? 400);
323
+ }
324
+
325
+ async flushAutoSave() {
326
+ clearTimeout(this._autoSaveTimer);
327
+ this._autoSaveTimer = null;
328
+ if (this._pendingAutoSave == null) return;
329
+ const html = this._pendingAutoSave;
330
+ this._pendingAutoSave = null;
331
+ const key = this.options.autoSaveKey;
332
+ const savedAt = Date.now();
333
+ try {
334
+ const adapter = this.options.autoSaveAdapter;
335
+ if (typeof adapter?.save === 'function') {
336
+ await adapter.save({ key, html, savedAt, context: this });
337
+ } else {
338
+ localStorage.setItem(key, html);
339
+ localStorage.setItem(key + ':asrmeta', JSON.stringify({ savedAt }));
340
+ }
341
+ this.triggerEvent('autoSave', { key, html, savedAt });
342
+ } catch (error) {
343
+ this.triggerEvent('autoSaveError', { key, error });
344
+ }
345
+ }
346
+
347
+ async loadAutoSave() {
348
+ const adapter = this.options.autoSaveAdapter;
349
+ if (typeof adapter?.load === 'function') {
350
+ return adapter.load({ key: this.options.autoSaveKey, context: this });
351
+ }
352
+ try { return localStorage.getItem(this.options.autoSaveKey); } catch (_) { return null; }
353
+ }
354
+
265
355
  // ---------------------------------------------------------------------------
266
356
  // Module invocation
267
357
  // ---------------------------------------------------------------------------
@@ -337,6 +427,37 @@ export class Context {
337
427
  // Public editor API
338
428
  // ---------------------------------------------------------------------------
339
429
 
430
+ /** Updates runtime-safe options without recreating the editor. */
431
+ updateOptions(overrides = {}) {
432
+ const next = mergeDeep(this.options, overrides);
433
+ Object.keys(this.options).forEach((key) => delete this.options[key]);
434
+ Object.assign(this.options, next);
435
+
436
+ const { container, editable } = this.layoutInfo;
437
+ if (Object.hasOwn(overrides, 'readOnly')) this.setDisabled(Boolean(this.options.readOnly));
438
+ if (Object.hasOwn(overrides, 'spellcheck')) editable.spellcheck = this.options.spellcheck !== false;
439
+ if (Object.hasOwn(overrides, 'placeholder')) editable.dataset.placeholder = this.options.placeholder || '';
440
+ if (Object.hasOwn(overrides, 'direction')) {
441
+ const rtl = this.options.direction === 'rtl';
442
+ editable.setAttribute('dir', rtl ? 'rtl' : 'ltr');
443
+ container.classList.toggle('an-dir-rtl', rtl);
444
+ }
445
+ if (Object.hasOwn(overrides, 'height') || Object.hasOwn(overrides, 'minHeight')) {
446
+ const height = this.options.height || this.options.minHeight || 0;
447
+ editable.style.minHeight = height ? `${height}px` : '';
448
+ }
449
+ if (Object.hasOwn(overrides, 'maxHeight')) {
450
+ editable.style.maxHeight = this.options.maxHeight ? `${this.options.maxHeight}px` : '';
451
+ }
452
+ if (Object.hasOwn(overrides, 'toolbar')) this.invoke('toolbar.rebuild');
453
+ // Start/stop option-gated modules (bubbleToolbar, mention, slashMenu, ...)
454
+ // so toggling them here behaves the same as passing them to create().
455
+ this._syncOptionalModules();
456
+ this.invoke('statusbar.update');
457
+ this.triggerEvent('optionsChange', { ...overrides });
458
+ return this;
459
+ }
460
+
340
461
  /**
341
462
  * Returns the current HTML content of the editor.
342
463
  * Zero-width spaces (U+200B) inserted by inline editing helpers are stripped
@@ -444,6 +565,64 @@ export class Context {
444
565
  return this.invoke('editor.getMarkdown');
445
566
  }
446
567
 
568
+ getSelectionBookmark() {
569
+ return this.invoke('editor.getSelectionBookmark') ?? null;
570
+ }
571
+
572
+ restoreSelectionBookmark(bookmark) {
573
+ return this.invoke('editor.restoreSelectionBookmark', bookmark);
574
+ }
575
+
576
+ async importDocument(format, data) {
577
+ const adapter = this.options.documentAdapters?.[format];
578
+ let html;
579
+ if (typeof adapter?.import === 'function') html = await adapter.import(data, this);
580
+ else if (format === 'html') html = String(data ?? '');
581
+ else if (format === 'markdown') { this.setMarkdown(String(data ?? '')); return this; }
582
+ else if (format === 'text') { this.setText(String(data ?? '')); return this; }
583
+ else throw new Error(`[AutumnNote] No importer registered for "${format}".`);
584
+ this.setHTML(html);
585
+ return this;
586
+ }
587
+
588
+ async exportDocument(format) {
589
+ const adapter = this.options.documentAdapters?.[format];
590
+ if (typeof adapter?.export === 'function') return adapter.export(this, this.getHTML());
591
+ if (format === 'html') return this.getHTML();
592
+ if (format === 'markdown') return this.getMarkdown();
593
+ if (format === 'text') return this.getText();
594
+ throw new Error(`[AutumnNote] No exporter registered for "${format}".`);
595
+ }
596
+
597
+ ensureBlockIds() {
598
+ const blocks = this.layoutInfo.editable.children;
599
+ for (const block of blocks) {
600
+ if (!block.hasAttribute('data-an-block-id')) {
601
+ const id = globalThis.crypto?.randomUUID?.() || `an-${Date.now()}-${Math.random().toString(36).slice(2)}`;
602
+ block.setAttribute('data-an-block-id', id);
603
+ }
604
+ }
605
+ return this;
606
+ }
607
+
608
+ getDocument() {
609
+ if (this.options.blockIds) this.ensureBlockIds();
610
+ return { version: 1, html: this.getHTML(), markdown: this.getMarkdown() };
611
+ }
612
+
613
+ loadDocument(documentData) {
614
+ this.setHTML(documentData?.html || '');
615
+ this.clearHistory();
616
+ return this;
617
+ }
618
+
619
+ applyRemoteHTML(html) {
620
+ this.setHTML(html);
621
+ this._suppressedRemoteHTML = this.getHTML();
622
+ this.clearHistory();
623
+ return this;
624
+ }
625
+
447
626
  /**
448
627
  * Returns the current word count of the editor content.
449
628
  * @returns {number}
@@ -597,9 +776,22 @@ export class Context {
597
776
 
598
777
  /**
599
778
  * Completely removes the editor and restores the original element.
779
+ *
780
+ * Teardown itself is synchronous; the returned promise only settles once the
781
+ * closing auto-save has finished, so `await editor.destroy()` is worth doing
782
+ * when using an async `autoSaveAdapter`. Ignoring the return value is safe.
783
+ * @returns {Promise<void>}
600
784
  */
601
785
  destroy() {
602
- if (!this._alive) return;
786
+ if (!this._alive) return this._destroyPromise ?? Promise.resolve();
787
+
788
+ // Start the final auto-save before tearing anything down. `_listeners` is
789
+ // deliberately kept alive until this settles, otherwise the closing
790
+ // autoSave/autoSaveError event fires into an already-cleared listener map
791
+ // and an async adapter's last write completes silently.
792
+ const pendingFlush = this._pendingAutoSave != null
793
+ ? this.flushAutoSave().catch(() => {})
794
+ : null;
603
795
 
604
796
  this._modules.forEach((module) => {
605
797
  if (typeof module.destroy === 'function') module.destroy();
@@ -637,7 +829,14 @@ export class Context {
637
829
  }
638
830
 
639
831
  this._alive = false;
640
- this._listeners.clear();
832
+
833
+ // Resolves once the closing auto-save (if any) has finished. Callers using
834
+ // an async autoSaveAdapter can `await editor.destroy()` to be sure the last
835
+ // write landed before unloading.
836
+ this._destroyPromise = Promise.resolve(pendingFlush).then(() => {
837
+ this._listeners.clear();
838
+ });
839
+ return this._destroyPromise;
641
840
  }
642
841
 
643
842
  // ---------------------------------------------------------------------------
@@ -647,9 +846,9 @@ export class Context {
647
846
  /**
648
847
  * Syncs editor HTML back into the original textarea/input for form submission.
649
848
  */
650
- _syncToTarget() {
849
+ _syncToTarget(html) {
651
850
  if (this.targetEl.tagName === 'TEXTAREA' || this.targetEl.tagName === 'INPUT') {
652
- /** @type {HTMLInputElement} */ (this.targetEl).value = this.getHTML();
851
+ /** @type {HTMLInputElement} */ (this.targetEl).value = typeof html === 'string' ? html : this.getHTML();
653
852
  }
654
853
  }
655
854
  }
@@ -7,16 +7,37 @@ export class History {
7
7
  /**
8
8
  * @param {HTMLElement} editable - the contenteditable element
9
9
  * @param {number} [limit=100] - maximum number of undo/redo states
10
+ * @param {number} [maxBytes=10485760] - maximum combined size (chars) of all
11
+ * stacked snapshots (html + tokenized image data). Oldest states are
12
+ * evicted first when exceeded, even if `limit` hasn't been reached —
13
+ * documents with many large embedded images can otherwise hold dozens of
14
+ * full-size copies in memory despite the step-count limit.
10
15
  */
11
- constructor(editable, limit = 100) {
16
+ constructor(editable, limit = 100, maxBytes = 10 * 1024 * 1024) {
12
17
  this.editable = editable;
13
18
  this._limit = limit;
19
+ this._maxBytes = maxBytes;
20
+ this._bytes = 0;
14
21
  /** @type {Array<{html: string, images?: Record<string,string>, sel: {start: number, end: number}|null}>} */
15
22
  this.stack = [];
16
23
  this.stackOffset = -1;
17
24
  this._savePoint();
18
25
  }
19
26
 
27
+ /**
28
+ * Approximate in-memory size (chars) of one stacked snapshot: the tokenized
29
+ * HTML string plus every image data URL it references.
30
+ * @param {{html: string, images?: Record<string,string>}} entry
31
+ * @returns {number}
32
+ */
33
+ _entrySize(entry) {
34
+ let size = entry.html.length;
35
+ if (entry.images) {
36
+ for (const key in entry.images) size += entry.images[key].length;
37
+ }
38
+ return size;
39
+ }
40
+
20
41
  // ---------------------------------------------------------------------------
21
42
  // Private helpers
22
43
  // ---------------------------------------------------------------------------
@@ -115,16 +136,26 @@ export class History {
115
136
  _savePoint() {
116
137
  // Trim future history if we're mid-stack
117
138
  if (this.stackOffset < this.stack.length - 1) {
139
+ for (const entry of this.stack.slice(this.stackOffset + 1)) {
140
+ this._bytes -= this._entrySize(entry);
141
+ }
118
142
  this.stack = this.stack.slice(0, this.stackOffset + 1);
119
143
  }
120
144
  const raw = this._serialize();
121
145
  const { html, images } = this._tokenizeImages(raw);
122
- this.stack.push({ html, images, sel: this._serializeSelection() });
123
- if (this.stack.length > this._limit) {
124
- this.stack.shift();
125
- } else {
126
- this.stackOffset++;
146
+ const entry = { html, images, sel: this._serializeSelection() };
147
+ this.stack.push(entry);
148
+ this._bytes += this._entrySize(entry);
149
+
150
+ // Evict oldest states first, whichever budget (step count or byte size)
151
+ // is exceeded — always keep at least the just-pushed current state.
152
+ while (this.stack.length > 1 && (this.stack.length > this._limit || this._bytes > this._maxBytes)) {
153
+ this._bytes -= this._entrySize(this.stack.shift());
127
154
  }
155
+ // The newly-pushed current state is always the final entry. Recompute the
156
+ // offset from the resulting stack instead of incrementing conditionally:
157
+ // a single oversized snapshot may evict several older entries at once.
158
+ this.stackOffset = this.stack.length - 1;
128
159
  }
129
160
 
130
161
  _restore(point) {
@@ -209,6 +240,7 @@ export class History {
209
240
  reset() {
210
241
  this.stack = [];
211
242
  this.stackOffset = -1;
243
+ this._bytes = 0;
212
244
  this._savePoint();
213
245
  }
214
246
 
@@ -0,0 +1,27 @@
1
+ /**
2
+ * i18n/all.js — Registers every bundled locale.
3
+ *
4
+ * Imported by the UMD/CDN entry point, where script-tag consumers have no
5
+ * bundler to tree-shake with and therefore expect `lang: 'vi'` to work out of
6
+ * the box. ESM consumers should import only the locales they need from
7
+ * `autumnnote/i18n/<code>` instead of pulling this in.
8
+ */
9
+
10
+ import { registerLocale } from './index.js';
11
+ import { vi } from './vi.js';
12
+ import { ja } from './ja.js';
13
+ import { zh } from './zh.js';
14
+ import { fr } from './fr.js';
15
+ import { de } from './de.js';
16
+ import { es } from './es.js';
17
+ import { ko } from './ko.js';
18
+
19
+ registerLocale('vi', vi);
20
+ registerLocale('ja', ja);
21
+ registerLocale('zh', zh);
22
+ registerLocale('fr', fr);
23
+ registerLocale('de', de);
24
+ registerLocale('es', es);
25
+ registerLocale('ko', ko);
26
+
27
+ export { vi, ja, zh, fr, de, es, ko };
package/src/js/i18n/de.js CHANGED
@@ -342,4 +342,19 @@ export const de = {
342
342
  restore: 'Wiederherstellen',
343
343
  discard: 'Verwerfen',
344
344
  },
345
+
346
+ slashMenu: {
347
+ noResults: 'Keine passenden Befehle',
348
+ heading1: 'Überschrift 1',
349
+ heading2: 'Überschrift 2',
350
+ heading3: 'Überschrift 3',
351
+ bulletList: 'Aufzählungsliste',
352
+ numberedList: 'Nummerierte Liste',
353
+ checklist: 'Checkliste',
354
+ blockquote: 'Zitat',
355
+ codeBlock: 'Codeblock',
356
+ horizontalRule: 'Horizontale Linie',
357
+ table: 'Tabelle',
358
+ image: 'Bild',
359
+ },
345
360
  };
package/src/js/i18n/en.js CHANGED
@@ -350,4 +350,19 @@ export const en = {
350
350
  imageSize: (maxSize) =>
351
351
  `Image file is too large. Maximum allowed size is ${maxSize} MB.`,
352
352
  },
353
+
354
+ slashMenu: {
355
+ noResults: 'No matching commands',
356
+ heading1: 'Heading 1',
357
+ heading2: 'Heading 2',
358
+ heading3: 'Heading 3',
359
+ bulletList: 'Bullet List',
360
+ numberedList: 'Numbered List',
361
+ checklist: 'Checklist',
362
+ blockquote: 'Blockquote',
363
+ codeBlock: 'Code Block',
364
+ horizontalRule: 'Horizontal Rule',
365
+ table: 'Table',
366
+ image: 'Image',
367
+ },
353
368
  };
package/src/js/i18n/es.js CHANGED
@@ -342,4 +342,19 @@ export const es = {
342
342
  restore: 'Restaurar',
343
343
  discard: 'Descartar',
344
344
  },
345
+
346
+ slashMenu: {
347
+ noResults: 'No hay comandos coincidentes',
348
+ heading1: 'Encabezado 1',
349
+ heading2: 'Encabezado 2',
350
+ heading3: 'Encabezado 3',
351
+ bulletList: 'Lista con viñetas',
352
+ numberedList: 'Lista numerada',
353
+ checklist: 'Lista de verificación',
354
+ blockquote: 'Cita',
355
+ codeBlock: 'Bloque de código',
356
+ horizontalRule: 'Línea horizontal',
357
+ table: 'Tabla',
358
+ image: 'Imagen',
359
+ },
345
360
  };