Cliquez pour modifier

:information_source: Summary Clicking in the textarea in the composer will select the corresponding line in the preview pane, and vice versa.
:hammer_and_wrench: Repository Link https://github.com/thijsbrilleman/discourse-click-to-edit
:open_book: Install Guide How to install plugins in Discourse

click-to-edit - 1080WebShareName-2

Features

Clicking in the textarea in the composer will select the corresponding line in the preview pane, and vice versa.

26 « J'aime »

Very nice addition to the core editing of Discourse. Thank you for creating it.

5 « J'aime »

Seems like something that should be pr welcome, though I have no say in that.

6 « J'aime »

Hello :wave: Thanks, this is really cool :tada: I am just thinking that it would be awesome to make it as a theme component. :slightly_smiling_face:

7 « J'aime »

It doesn’t work too well on iPad, because it is choosing whole text when writing. It looks very odd.

3 « J'aime »

Thanks, and I agree. Will look into it as soon as I have time. You’d always be welcome to file a pull request.

This currently is intended behavior, but I am of course open to better ideas. What sort of visual queue would you recommend?

2 « J'aime »

It would show as pasted text when something is really selected. Then there would be action and response.

Curious, why is this a plugin vs theme component? All this tokens can be generated client side no?

Nice job btw, love that you are leaning on line numbers injected by the markdown engine.

4 « J'aime »

Thank you Sam.

As you might have noticed, the data-ln attributes are present in the cooked html generated and stored on the server as well.

I implemented this behavior, so that later on I could extend the plugin to allow reliable insertion/editing of fragments from the topic view page, equivalent to the edit-button shown below (but a bit more robust):

The image is a screenshot of a web browser showing a quote soaking window with options to edit, copy, and quote.  (Captioned by AI)

It’s been a year since I wrote it, but if I remember correctly, to that end in plugin.rb the line

register_asset "vendor/javascripts/markdown-it-line-numbers.js", :vendored_pretty_text

is required to make sure the MarkdownIt extension also runs server-side when cooking the html.

I have not found the time required to implement the extended edit feature though, so if that requirement is dropped it could be converted to a component I guess.

5 « J'aime »

@sam I’m looking into converting it into a theme component, but I’m unable to figure out how to get this code executed in the context of a markdownit plugin:

// javascripts/lib/discourse-markdown/initialize_markdownit_plugin.js:

export function setup(helper) {
    helper.registerPlugin(markdownitLineNumbers); // markdownitLineNumbers already available
}

I have the suspicion that the line in the plugin I wrote earlier sprinkles some client-side magic as well:

# plugin.rb

register_asset "vendor/javascripts/markdown-it-line-numbers.js", :vendored_pretty_text`

Do you have any clue?

Not sure, will ping the team.

2 « J'aime »

I believe this is because it is currently restricted to plugins scope only. It would work without that check. (This code has been introduced in this commit)

I wanted to integrate line-number for another component, but I did not want to make a plugin, so I gave up on it. It would be super cool if markdown features could be supported in theme components!

On a side note, a great feature that you proposed here – very nice. :+1: :rocket:

4 « J'aime »

Ah yes, this clears it up.

Looking at this code, it might be possible to manually inject the markdown plugin from the theme component at run-time, but this would be pretty hacky. I’ll await the verdict from the core team before trying to implement it.

4 « J'aime »

Our markdown pipeline runs both on the client (for preview), and on the server (to pre-render the HTML for posts). So that’s why it’s designed for plugins only - they’re the only ones which can inject code on the server-side.

Now… this case is quite unusual, since the extension is only needed in the composer, and not on the server. So doing it from a theme component should be feasible.

Did you have a particular strategy in mind for this?

5 « J'aime »

This seems like something that would have wide appeal. It can be hard to find your place in a long post. Might it be pr-welcome ?

5 « J'aime »

Override this function in the original codebase:

// discourse/app/assets/javascripts/discourse/app/components/d-editor.js
async cachedCookAsync(text, options) {
  this._cachedCookFunction ||= await generateCookFunction(options || {});
  return await this._cachedCookFunction(text);
}

with a theme component initializer:

export default {
  name: "d-editor-cached-cook-async-override",
  initialize() {
    const dEditor = require("discourse/components/d-editor").default;
    dEditor.reopen({
      cachedCookAsync(text, options) {
        // duplicate code here to return an altered cook function
      },
    });
  },
};

It would mean quite a bit of code duplication, if it’d work at all. Dirty, dirty.

4 « J'aime »

Hmm yeah, agreed - definitely not ideal. Duplicating the code might not even be possible, because the markdown-it modules are loaded asynchronously, and aren’t part of the amd module system which themes/plugins have direct access to. :thinking:

Building a system to allow themes to contribute client-side-only md transformations could be cool, although the use-cases are fairly limited. In 99% of cases, people want md transforms to apply server-side as well.

So I think, for now, sticking with a plugin is probably the best approach.

5 « J'aime »

I wonder if this kind of decoration should be applied regardless though?

Eg:

<p data-source-line="0">.....</p>

The extra data attribute will assist a lot of internal implementations we have, like, for example, not showing autocomplete when you are inside a code block. Also quoting and quick edit become much easier.

The trivial implementation carries almost no extra weight, but allows us to delete a pile of source code.

7 « J'aime »

We had this in the past (behind a flag), but it was removed in this commit. I found this screenshot from some internal discussions about that feature:

i.e. the perf issue was with the scroll syncing code, not the injection of the line-numbers :ok_hand:

So yeah, I have no objection to adding the data-source-line injection into core, as long as it’s only added in preview. Is it something you’d be interested in making a PR for @pipkin?

4 « J'aime »

Gladly! Happy to be able to give something back to you guys.

6 « J'aime »