I started building my own text editor earlier this summer as a way to hone my skills and teach myself more about how text editors work behind the scenes. Being the control freak that I am, I wanted to have a text editor that I knew the inner workings of. I didn't want to be left confused when I couldn't add a certain file types, or be unable to make changes to my text due to outside restraints. I wanted to be completely familiar with the software I would be creating my blog posts on, and not be left to the whims of another programmer to decide what I can and can't do with my own writing.
So, I turned to ChatGPT. A.I. told me that it would probably take a few weeks to a month to build and design my own rich text editor. I scoffed and didn't believe it. Surely that could not be true. How difficult could it really be? I already knew how to create many of the required scripts. I could create font-family drop-down to toggle fonts, colors, sizes, etc. I could build CRUD systems, and I understand the importance of stability, so I could make this system perform better than any current open-source programs.
Let's just say, I may have overestimated my abilities.
I began by creating a hidden input field and a text area box. Simple enough. Then I added some buttons: toggle bold, italic, underline, and strike. I got that working pretty easily, and was able to apply those styles in my text editor in almost no time.
Then, I wanted to add a custom font menu, the ability to change sizes, colors, and alignment. Things got a little more challenging at this point, but it wasn't anything extraordinary. The largest difficulty I faced here was getting everything modularized and talking to each other, which felt a little more time-consuming than I would have liked, but I was eventually able to get it done.
I had only spent a few hours working on my text editor and was starting to feel like I could do anything. I was applying font families, changing colors, making things bold and underlined like it was the 90's and I had just discovered the internet.
Then I ran into my first problem. Yes, I could apply these styles one at a time. I could make the color blue, or change the size to 60. But could I make it blue and size 60? Not at the same time, no, I couldn't. So, I added an html-view to see what was going on behind the scenes.
Quickly, I noticed a problem that I have seen in so many other text editors: nested spans, stray html tags: messy, sloppy code that the computer could no longer read. My perfect word editor was not so perfect after all! I couldn't let all of my work be for nothing, and I still wanted a custom text editor.
So, I began to create an applyStyle function that would compute all my applied styles, push them together into one tag block, and delete anything redundant or unnecessary. At first, this was great. It was working. I could now apply many combinations of color, size, font-family, etc.
I believe I was on Day #2 at this point, and felt on top of the world. I knew this wasn't going to be difficult for me.
After adding several more fun features, such as the ability to input headings, 2 column layouts, a drawing tool, an emoji picker, media uploader, and other standard text editor tools, it came time to actually put it to use. I was excited to write my first blog post on a rich text editor that I had built myself. The applyStyle function was stopping endless span nonsense, my layout system felt stable, and I was ready to go. I began typing a post about my recent move to New York, and then I realized how deep the problems with my text editor really were.
Sure, I could create a paragraph of text and apply styles as I pleased. But then, I wanted to add a numbered list. I hit my numbered list button after my typed paragraph, began putting some list items into place, and then went to style them in a different color so they would stand out against the rest of my text.
Imagine my surprise when my ENTIRE paragraph deleted above the bulleted list!
I quickly realized that my applyStyle function was combining nested spans. Although this was exactly what I wanted, it also meant that spans were getting mixed together when they should have been left separated. I would add a new span, change the style on that span, and if it was already combined with another span, random blocks of text would get deleted, styles would go missing, and everything was generally just a huge, giant, mess!
I was a few days into my project at this point, and spent a lot more time refining my applyStyle function. I also added some cleaners to merge adjacent spans, properly close spans, create new ones that would not get merged on enter, and so on. Still, every time I thought I had the answer to one problem, another would arise.
When I reached a point when things felt pretty nice, one of the problems I had left was cursor/carat positioning. I would add text, size it up in my text editor, and then size it back down, but the carat size would remain the exact same. I experimented with different cursor controls, but these would interfere with my other functions, or they would cause text to jump around the editor, overflow off the side of the text area field, or reset the current computed style completely.
I was frustrated, and felt like I needed a quick solution. Even though I wanted to build it all myself, I knew that I had to rely on external framework to help me make this text editor more stable. I started looking for options, and found Quill. It seemed like a good choice: well documented, customizable, and could do everything that I needed it to do.
I began converting my existing text editor into a Quill editor. I kept the general structure and features of my text editor alive, but decided to rely on Quill to handle things like applyStyle, cursor controls, and monitoring spans. This was approximately one week into my journey of building a text editor from scratch. I thought back to what ChatGPT had told me about the estimated length of my project and laughed. I definitely understood why it had told me it would take a few weeks, although I still felt confident because it had only been a week... not a few!
After getting Quill all wired up into my existing text editor, I started running into very similar problems to the ones I was already experiencing with my own editor. Examining the html, I was still seeing nested spans, random deletions, and the icing on the cake was that the entire system looked ugly. While documentation was good for the actual text editor features, when it came to styling the editor, its buttons, and just the look and feel of the whole program, I was lost.
I felt frustrated because now, the stability of my editor had barely improved, and now it didn't feel like my editor at all. I decided to switch back to my own code, and decided that I could rely on some outside help to get everything stable. I had spent an entire day converting everything over to Quill, just to put it back the next day, which also took an entire day. Two whole days wasted, and on day three of the second week, I had to keep pushing forward to try to make my own code stable.
Overall, things went well and I learned a lot. I was able to get my program working again pretty well. I added autosave capability, a tagging system, and many, many, functions to help my text editor perform the way I wanted.
Yet, at the end of it, I remember writing in it and it still just did not feel... right. I felt like at any moment, something could come undone and escape all of my hard work by deleting my writing. I was experiencing some bugs still. I remember thinking: it isn't bad to lean on outside help. Everything here is built, I just need a little extra "umpf" to make things perfect.
That is when I decided I would try to implement EditorJs, another text-editor ecosystem that I believed would help improve the stability of my text editor due to its reliance on block-style elements, rather than spans. It was easy to implement, and had things going in just an hour or two. It did feel better: having that little block element there before I began typing did make things feel more secure, and I enjoyed playing with different features to add to my inline-editor stack.
Then I hit a serious road block. As I tried to get my font-size and font-family menu integrated and working with EditorJS, I realized there was no native capability for this, and I would need to use a plug-in. Ok. Great, I found a plug-in. This plug-in, though, it kept throwing error after error message: scoping was incorrect, everything was firing at the wrong time, syntax errors, the list went on and on.
Eventually, I decided to use all my existing code to create my own plug-in, a capability that EditorJS boasts. It was supposed to be easy, and honestly, it was. The trouble was this: EditorJS depended on block-level elements in order to save. My plugins were using spans, and while that didn't necessarily matter when working within the text-editor, it was a huge deal when it came to my autosave functions and the actual rendering of text styles on my blog.
EditorJS would not save any of my self-made plug-ins. I could save my writing, and any style that was applied directly through EditorJS, but no matter what I did, I could not get it to save font-size, font-family, or color.
I felt furious at this point. I was so annoyed that a system that claims to be a rich text editor would not have included these features as native capabilities.
I tried other plug-ins: I could get a font-family picker with them, yes. However, I would not be able to integrate my own font menu into the plug-in, meaning I would never be able to use any of the fonts I have already meticulously collected and curated for my own design work. This defeated the purpose in many ways. I depend on my font collection for my work. Not only that, but I have my own custom designed fonts using my own handwriting, and I would NEVER be able to use those.
I was back to square one again. I was in the middle of WEEK THREE at this point, and felt like giving up. I knew that was not an option, though, as I had already spent so much time working on this and needed to get it right.
I took a break for a few days: thought things through, sat and considered my logic and flow, read Stack Overflow, asked ChatGPT, and considered other frameworks I could potentially work with instead.
Eventually, I found Summernote. Summernote is a Javascript library that seemed to be exactly what I needed. I could use all my existing Javascript, but just route it through Summernote to help make things feel more secure. Reluctantly, I pushed on with my project and implemented a THIRD system for my text editor. I felt worn down, incapable, and honestly, seriously confused.
My files had gotten messy throughout this process. I couldn't tell what was leftover from EditorJS, what was my code, what was Quill. I had backups that weren't cleaned, CSS that had become dependent on one system and would break as I implemented a new one, and an autosave feature that I had built and rebuilt about four times already.
Yet, once I got things up and running with Summernote, I gained back confidence. Not only did things start working, but it actually still retained the look and feel of my custom created editor. That was the wonderful thing: it still was my custom editor. I retained my personalized font menu, my emoji picker, my media uploader, tagging system, and autosave was able to effectively store and retrieve all of my styles. I didn't have to give anything up (except a boat load of my time)!
Now, my editor is up and running. I have learned so much about how text editors actually work under the hood, and all the little quirks and confusions that go along with them. I am writing this on the editor now, and things feel smooth, powerful, and uniquely my own.
That is the thing that is so important to me in the end: the feeling of making something my own. When it comes to computer programs, software, my website, and my designs, I don't ever want to be told what I can and can't do. I want full control over my own work and my ability to create. I feel like Summernote completely allows that. All my code and my ideas remain intact, I just have Summernote quietly running in the background to make sure things stay neat and organized.
In the end, I think the most important lesson I learned from this project was that it is perfectly fine to rely on external frameworks, but I need to make sure that I do my research before jumping into a new system. I can't find something, read a couple reviews, and then just start plugging ahead. Although that does often feel like the best course of action in order to get projects finished quickly (meeting deadlines is super important), in the end, you sacrifice time if you choose the wrong system. I had to build and break down three different ecosystems in order to achieve my desired result. If I had taken a beat, done my research, and made sure that what I was implemented was exactly what I required for the project, I would have been a lot better off.
Still, I am proud of my work and know that it has made me a better builder in the long run. Some of these lessons need to be learned the hard way, and I am thankful that I am learning them now.