Code Monkey home page Code Monkey logo

richtextkit's People

Contributors

danielsaidi avatar dnzlk avatar dominikbucher12 avatar itsliamdowd avatar jake-b avatar jamesbradleym avatar jdelano avatar martindufort avatar mcrich23 avatar mhasan341 avatar msrutek-paylocity avatar ropellanda avatar willmorris44 avatar yaroslav2308 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

richtextkit's Issues

Make is possible to replace text at range

We can currently use the context to select a range, but not replace the currently selected text.

This should be possible when replacing text.

Replace the pasteText function with an insertText(at: position) (non-replacing) and insertText(at: range) (replacing).

iOS shared context between multiple RichTextEditor Instances causes Publishing change in view update warning.

Having multiple RichTextEditor instances with a shared context causes the xcode editor to overload with "Publishing changes from within view updates is not allowed, this will cause undefined behavior." ultimately leading to a crash.

Commenting out func textViewDidBeginEditing and func textViewDidEndEditing in the RichTextCoordinator swift file prevents this error but currently unsure of unintended consequences of this.

Screenshot 2023-02-24 at 12 20 37 PM

Input Lag on macOS Demo

The input lags on the macOS demo app. I profiled the demo app in Instruments, and found that the toolbar was redrawing with each character I typed. Removing the toolbar (particularly FontPicker) from the view hierarchy caused the app to behave as expected.

RichTextKit SwiftUI Profiler

Add support for focus values

To properly add support for macOS and iPadOS menu commands, we need focus values.

Make the rich text editor bind its context to a focus value, then use this context in the menu commands.

Is anyway to add to-do list and table into the text view

Hi everyone!

I'm working on the RichText feature, which requires adding a to-do list and drawing the table when editing, and so far, I can add the location and audio method. I try to implement it myself, but I need to gain experience.

Note_preview

Some styles are not reset when moving the cursor on macOS

On macOS, the background and foreground colors aren't reset when moving the text input cursor from colored text to a plain text.

image

In the image above, all text was plain. I then made the leftmost text green. When I then moved the cursor to the end of the text and continued typing, the green color was still applied.

Add support for affecting the entire text range

Some rich text writers should support easily affecting the entire text range.

The functions will be modified so that the range parameter is optional and uses the richTextRange if no range is provided.

This will initially be added to:

  • RichTextAttributeWriter
  • RichTextColorWriter
  • RichTextFontWriter
  • RichTextStyleWriter

Add support for keyboard shortcuts

The various buttons should have opt-out keyboard shortcuts applies, for instance:

  • Style buttons and toggles - cmd+b, cmd+I, cmd+u
  • Action buttons and toggles - cmd+c, cmd+v, cmd+z, cmd+shift+z

rtf file Color problem

I am reading attributed text from rtf file.

try! NSAttributedString(data: data!, options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.rtf], documentAttributes: nil)
and set these text to EditorScreen

RichTextEditor(text: $text, context: context,format: .rtf) { $0.textContentInset = CGSize(width: 10, height: 20) }

but colors not appearing.

If I set same text to TextView. Colors appearing

Something manipulating reader attributed text but I couldn't find

UIKit Example

If this can be use for UIKit where is the example or do I have create the SwitfUI to UIKit bridging file?

Add support for links

It should be possible to add a link to the current selection, and remote the link if there is already one.

  • Add support for adding a link to the the current text position.
  • Add support for removing a link from the current text position.
  • Add support for detecting a link at the current text position.
  • Add standard icon
  • Add it to the demo

Not possible to set new text

After creating a rich text editor, it's not possible to completely replace the current text. Doing so currently doesn't do anything. The reason why I tag this as a feature and not a bug is that it's a known limitation in the current implementation.

This should be possible, though, so a future update should fix this.

Toolbar

How to add RichTextKeyboardToolbar when using in a UIKit project.

Changing text position redraws entire app

This is related to #5

While investigating, I added a random color to parts of the demo app. It turns out that the entire app redraws every time the text position is moved:

image image

This is because the RichTextCoordinator syncs the text field's selectedRange to the RichTextContext when the text position changes, which happens when you move the cursor or type in the text field.

This is horrible for performance, but I don't know how to fix it. The rich text context is synced in full with the text field, which means that views that take the context as observed object will redraw if the range changes, even if they don't use the range.

Any input to help me fix this problem would be greatly appreciated.

Dynamic Editor Height Question

Is it currently possible to make the RichTextEditor frame dynamic with the following behavior?

  • Defined minimum and maximum height
  • When the current height is > min, and < max, no scrolling enabled
  • When the max height is reached, enable scrolling

Keyboard toolbar modifier doesn't work

Since RichTextKit wraps UIKit and AppKit, the SwiftUI toolbar view modifier with keyboard placement doesn't work.

In other words, this will not work:

RichTextEditor(text: $text, context: textEditorContext)
    .frame(minHeight: 200)
    .toolbar {
        ToolbarItem(placement: .keyboard) {
            Button {
                richTextContext.isBold.toggle()
            } label: {
                Image(systemName: "bold")
            }
        }
    }

In my own app, I developed a custom toolbar that was pinned above the keyboard. The library should offer this custom toolbar as a feature.

Add support to automatically split up text in paragraphs

It would be nice if the text editor could automatically detect when a new sentence should be added to a new paragraph, for instance after a certain number of sentences.

For instance, if I ask Chat GPT to Can you divide this text into paragraphs? for this text:

Once upon a time in a small village nestled in the mountains, there lived a young girl named Lily. She possessed a curious spirit and an insatiable love for adventure. One day, while exploring the woods near her home, she stumbled upon a hidden cave. Intrigued, she entered cautiously, discovering a dusty, ancient book with a worn leather cover. As Lily opened the book, a magical portal appeared, transporting her to a mystical realm called Evermore. In Evermore, she encountered fantastical creatures, enchanted forests, and breathtaking landscapes. Guided by an old, wise owl named Orion, Lily embarked on a quest to restore the balance between light and darkness. Along her journey, she encountered a mischievous sprite named Ember, who became her loyal companion. Together, they faced numerous challenges, including treacherous riddles, fearsome monsters, and tests of courage. Lily's determination and Ember's cleverness proved to be a formidable combination. With each obstacle overcome, Lily grew wiser and stronger, unlocking hidden powers within herself. As they delved deeper into Evermore's secrets, they discovered an ancient prophecy foretelling a cataclysmic event that would engulf the realm in eternal darkness. Lily realized that she was the chosen one, destined to fulfill the prophecy and save Evermore. The fate of an entire world now rested on her young shoulders. With unwavering bravery, Lily confronted the malevolent sorcerer responsible for the impending darkness. In a climactic battle, she tapped into her newfound powers, weaving spells of light and hope. The sorcerer, vanquished by her courage, was defeated, and the realm of Evermore was saved. As a token of gratitude, the creatures of Evermore bid Lily a fond farewell, and she returned to her village. Though she had changed, her heart remained filled with wonder and the knowledge that magic existed not only in distant realms but within herself. Lily became an inspiration to her fellow villagers, reminding them to embrace adventure and the boundless possibilities of the unknown. And so, the story of Lily, the young girl who journeyed through the realm of Evermore, lived on as a testament to the extraordinary power of belief, courage, and the timeless allure of a world where anything is possible.

we get:

Once upon a time in a small village nestled in the mountains, there lived a young girl named Lily. She possessed a curious spirit and an insatiable love for adventure. One day, while exploring the woods near her home, she stumbled upon a hidden cave. Intrigued, she entered cautiously, discovering a dusty, ancient book with a worn leather cover.

As Lily opened the book, a magical portal appeared, transporting her to a mystical realm called Evermore. In Evermore, she encountered fantastical creatures, enchanted forests, and breathtaking landscapes. Guided by an old, wise owl named Orion, Lily embarked on a quest to restore the balance between light and darkness.

Along her journey, she encountered a mischievous sprite named Ember, who became her loyal companion. Together, they faced numerous challenges, including treacherous riddles, fearsome monsters, and tests of courage. Lily's determination and Ember's cleverness proved to be a formidable combination. With each obstacle overcome, Lily grew wiser and stronger, unlocking hidden powers within herself.

As they delved deeper into Evermore's secrets, they discovered an ancient prophecy foretelling a cataclysmic event that would engulf the realm in eternal darkness. Lily realized that she was the chosen one, destined to fulfill the prophecy and save Evermore. The fate of an entire world now rested on her young shoulders.

With unwavering bravery, Lily confronted the malevolent sorcerer responsible for the impending darkness. In a climactic battle, she tapped into her newfound powers, weaving spells of light and hope. The sorcerer, vanquished by her courage, was defeated, and the realm of Evermore was saved.

As a token of gratitude, the creatures of Evermore bid Lily a fond farewell, and she returned to her village. Though she had changed, her heart remained filled with wonder and the knowledge that magic existed not only in distant realms but within herself. Lily became an inspiration to her fellow villagers, reminding them to embrace adventure and the boundless possibilities of the unknown.

And so, the story of Lily, the young girl who journeyed through the realm of Evermore, lived on as a testament to the extraordinary power of belief, courage, and the timeless allure of a world where anything is possible.

Foreground color is not persisted

If you set a text color with the current implementation, the text view is properly updated. You can try it out in the demo app.

However, if you save the rich text to file or write its data to NSUserDefaults and then restores the rich text, everything that is currently supported by the library (font, font size, background color, style etc.) is restored, except the text color.

The text color is handled exactly like the background color, except that it uses the foregroundColor key instead of the backgroundColor, so I just can't understand why this single thing doesn't work.

On MacOS/SwiftUI how do you use keyboard to submit?

On macOS Is there a simple way to allow "enter" key to submit on RichTextEditor ? I actually couldn't find this feature on the SwiftUI TextEditor either.

I want standard text input for a chat view. Enter submits text, shift+enter adds new line.

Any insight, much appreciated!

Investigate secure coding when archiving with NSKeyedArchiver

When the RichTextDataReader uses NSKeyedArchiver to generate archived data, it doesn't use secure coding. This can lead to errors when the file is unarchived.

For instance, this error was suddenly thrown after editing a file:

UserInfo={NSDebugDescription=value for key 'NS.objects' was of unexpected class 'AFAnalyticsTurnBasedInstrumentationContext' (0x210af22a8) [/System/Library/PrivateFrameworks/AssistantServices.framework].

This seems to be caused by some private frameworks, but we still have to handle it somehow.

We can try to change this RichTextDataReader function:

func richTextArchivedData() throws -> Data {
    try NSKeyedArchiver.archivedData(
        withRootObject: richText,
        requiringSecureCoding: false
    )
}

to use secure coding, but we then have to make sure that the invalid content doesn't cause the archive to fail.

Images are not initially resized on iOS

When adding an image to a RichTextEditor in a document-based iOS app, the image is correctly resized.

However, when later opening the document with the image, the image is not initially resized to fix the screen. As you then start to type, the image is resized as the text changes.

Improve demo app

The demo app is currently functional, but not designed at all.

We should adjust it to look like e.g. Notes, Pages, Word or Google Docs.

Adding Clear Text Editor Content

i tried to add a button to clear the content of the text editor but it is not working. The content is not being cleared

Button("Clear") {
clearContent()
}

private func clearContent() {
text = NSAttributedString()
}

Add support for strikethrough

It should be possible to apply a strikethrough style.

  • Add support to the views, context, coordinator etc.
  • Add standard icon
  • Add it to the demo

Support inserting arbitrary NSAttributedStrings

Hey there! This is a phenomenal library. Best that I've seen by far for SwiftUI rich text w/out forcing UIKit paradigms.
One major enhancement that would make this library even more powerful -- allowing for arbitrary NSTextAttachments. The functionality to support inserting NSTextAttachments has already been implemented internally for the RichTextImageAttachment capability.

An idea on implementation:

  • Expose a similar method to pasteImages or pasteText that instead of [ImageRepresentable] or String accepts a NSAttributedString (that could include an NSTextAttachment).
  • Then, as it would be impossible to encode/decode arbitrary data that could be included in these inserted strings, simply ignore those values when encoding/decoding to standard file formats and leave the responsibility for encoding/decoding to the library-user
    func pasteImages(
        _ images: [ImageRepresentable],
        at index: Int,
        moveCursorToPastedContent: Bool = false
    ) {
        #if os(iOS) || os(tvOS) || os(macOS)
        guard validateImageInsertion(for: imagePasteConfiguration) else { return }
        let content = NSMutableAttributedString(attributedString: richText)
        let insertRange = NSRange(location: index, length: 0)
        let safeInsertRange = safeRange(for: insertRange)
        let insertedItems = images.count * 2   // The number of inserted "items" is the images and a newline for each
        let safeMoveIndex = safeInsertRange.location + insertedItems
        let attributes = content.richTextAttributes(at: safeInsertRange)
        let attributeRange = NSRange(location: index, length: insertedItems)
        let safeAttributeRange = safeRange(for: attributeRange)
        images.reversed().forEach {
            performPasteImage($0, at: index)
        }
        mutableRichText?.setRichTextAttributes(attributes, at: safeAttributeRange)
        if moveCursorToPastedContent {
            moveInputCursor(to: safeMoveIndex)
        }
        #else
        assertionFailure("Image pasting is not supported on this platform")
        #endif
    }

This would just be the first step in allowing for arbitrary subviews to be included in the RichTextEditor, but would enable a future update to support custom sub-classed NSTextAttachments like here:

screenshot

References:

Some libraries that implement this type of functionality:

Keyboard Toolbar not displaying

Hey I'm trying to ad a toolbar to the RichText Editor in SwiftUI and it doesn't seem to display. Here is what my code looks like:

` @StateObject var context: RichTextContext = RichTextContext()

@State var text: NSAttributedString = NSAttributedString(string: "type here....")

var body: some View {
    RichTextEditor(text: $text, context: context)
        .toolbar {
            ToolbarItemGroup(placement: .keyboard) {
                RichTextKeyboardToolbar(context: context) {
                    
                } trailingButtons: {
                    
                }
                
            }
        }
}`

Screenshot 2023-04-26 at 9 40 52 PM

Newlines not being indenting until adding additional text

Hello,

Thanks for your great work, I just started a project this Friday, and you package has beet a huge help!

One problem that I have not been able to solve it to see the cursor indent after hitting enter on the keyboard (new line). The indent works fine if there is no next in the text editor field. It this seems like a bug to me, because the user would have to start typing on that new line before he sees the cursor indent.

I apologize if it is error on my part, but I can't find a workaround.

Thanks in advance,

David Alvarez
[email protected]

Add support for macOS menu commands

The macOS app should have support for menu commands, for instance:

  • Styles - cmd+b, cmd+I, cmd+u
  • Actions - cmd+c, cmd+v, cmd+z, cmd+shift+z

RichTextEditor cycle in updateUIView

Hello,

The following code in RichTextEditor causes swift warning Publishing changes from within view updates is not allowed, this will cause undefined behavior. Also because we update UI from within updateUI function, it causes infinite loop and does not allow to get past the point.

public func updateUIView(_ view: UIViewType, context: Context) {
        textView.attributedString = text.wrappedValue
        richTextContext.highlightedRange = nil // This causes cyclic update to UIView 
    }
bug.mov

Workaround:

Delete the assignment of highlightedRange

Xcode Version: 14.3 (14E222b)
iOS 14 Simulator (or any other)

Storing to core data

A hint for those who need to store the text to core data: set the field to "Transformable".

The vars are declared like:

@State var information = NSAttributedString(string: "")
init() {
_information = State(initialValue: Entity.Attribute as! NSAttributedString)
}

Add ways to group buttons together

To increase the visual clarity of e.g. the format toolbar, RichTextKit should have a way to group buttons together.

Using a reusable component, we will then be able to group action buttons and toggles together like this:

toolbar-stylegroup-segmented

Compress images further

When adding a 2.6MB HEIC file to a document, the resulting file becomes 6MB+, which about corresponds to the file size you get when you convert the HEIC file to JPEG on disc.

The image in question is 4032 pixels wide, which I think could be scaled down. We should at least provide an image setting that lets us set the max file size or dimensions, and scale down any images accordingly.

Support adding image

I'm wondering if it's possible to add image to the editor from photo album or directly from camera and resize it by gesture.

If you don't support it now, what is your suggestion to add this feature? Thanks.

How to set `standardRichTextFontSize`?

How do I set the standardRichTextFontSize for my editor?
The package file itself is not editable.

RichTextEditor(text: $textBodyAttrib, context: context) {
	$0.setCurrentFontSize(to: 11)
}

is not working properly and is overwritten.

Add support for letter spacing

It should be possible to adjust the letter spacing.

When implementing, do this:

  • Add support to the views, context, coordinator etc.
  • Add standard icon
  • Add it to the demo

Catalyst support

Hello, I was wondering if you'd consider adding Catalyst support. Right now because of several AppKit code blocks, it's not possible to compile the project for Catalyst. I believe the issue is that the blocks in #if canImport(AppKit) will try to run in Catalyst, but some macOS classes are not available in Catalyst. An extra check for #if targetEnvironment(macCatalyst) should do the trick.

For my project I was able to use the library by adding the source code locally and removing the incompatible appkit code.

Screenshot 2023-03-14 at 16 02 55

Menus for Adding Text at Cursor Position

As this cool RTE is OpenSource, I'd like to share a small peace of code for a nice additional feature.

Background: I have to write many letters and very often I have to add the same piece of text, that I call "snippet".
Therefor add an extra Menu (e.g. to the TopToolBar)

Menu {
	ForEach(snippets, id: \.self) { snippet in
		Button {
			context.pasteText(snippet.text!, at: context.selectedRange.location, moveCursorToPastedContent: true)
		} label: {
			Text(snippet.title!)
		}
	}
} label: {
	Text("insertSnippet")
}
.help("help_selectMarker")

Snippets here: a FetchedResults from Core Date

Have fun.

Add unit tests

The OribiRichTextKit unit tests have not yet been ported.

We should do this before releasing 0.2.

Add support for line height

It should be possible to adjust the line height.

  • Add support to the views, context, coordinator etc.
  • Add standard icon
  • Add it to the demo

How to save content from the RichTextEditor?

First off, please accept my gratitude for this lovely package! A smart, modern component to act as a rich text editor is exactly what my AppKit-based application needs right now. While I initially attempted to integrate just the view, I ultimately decided to go all-in with the SwiftUI-based RichTextEditor component, as a hedge to future-proof at least this part of my app. My SwiftUI-fu is a tad weak, particularly around data issues, so I'll apologize if this is a dumb question. But I note that your sample app doesn't provide a Save feature, and that's exactly what I want to be able to do at this point โ€”ย I can get an NSAttributedString out of a file on disk and into the editor. I can use the editor component to edit text. But I cannot figure out how to save that text. While I have an ObservableObject providing the content, it doesn't appear that the attributed string property is being updated as the user works the editor; so when I save, it's the same content as was originally read off disk. Here's some code:

I'm using an EditorContent object from my app to contain the relevant file data:

class EditorContent: NSObject, ObservableObject {
    @Published var item: FilesystemItem
    @Published var fileURL: String
    let isReadOnly: Bool

The FilesystemItem is another ObservableObject that has an text property, which is the NSAttributedString content from the file on disk. This gets fed to the RichTextEditor...

editorVC = NSHostingController(rootView: EditorView(editorContent: content))
<add to view>

which is set out pretty much as your sample app has it:

struct EditorView: View {
    @ObservedObject var editorContent: EditorContent
    @StateObject var context = RichTextContext()

    var body: some View {
        VStack {
            RichTextEditor(text: $editorContent.item.text, context: context) {
                // You can customize the native text view here
                $0.textContentInset = CGSize(width: 40, height: 40)
            }
            .focusedValue(\.richTextContext, context)
        }
    }
}

I note that your sample app's actions execute from the RichEditorContext, but that doesn't seem to have access to the textview, or the RichTextCoordinator, which does. I'm kind of scratching my head trying to sort out the hierarchy, and hoping that you can set me in the right direction?

Thanks again!

Improve iOS demo

Make the iOS demo use more standard menus and stuff for working with styles, actions etc.

RichTextStyleToggleGroup not showing color

Hello again,

I noticed that the "buttonStyle" is not being applied (color now showing active color) when using the RichTextStyleToggleGroup. It's possibly due to the fact that the RichTextStyleToggleGroup uses a ControlGroup. My workaround was just to create the RichTextStyleButton myself.

Thanks in advanced,

David Alvarez
[email protected]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.