diff --git a/app/assets/javascripts/discourse-markdown-it/src/features/anchor.js b/app/assets/javascripts/discourse-markdown-it/src/features/anchor.js index 78027d6f2f1..d9333da723f 100644 --- a/app/assets/javascripts/discourse-markdown-it/src/features/anchor.js +++ b/app/assets/javascripts/discourse-markdown-it/src/features/anchor.js @@ -5,6 +5,8 @@ export function setup(helper) { helper.registerPlugin((md) => { md.core.ruler.push("anchor", (state) => { + const postId = helper.getOptions().postId; + for ( let idx = 0, lvl = 0, headingId = 0; idx < state.tokens.length; @@ -45,6 +47,10 @@ export function setup(helper) { slug = `${slug || "h"}-${++headingId}`; + if (postId) { + slug = `p-${postId}-${slug}`; + } + linkOpen.attrSet("name", slug); linkOpen.attrSet("class", "anchor"); linkOpen.attrSet("href", "#" + slug); diff --git a/app/assets/javascripts/discourse-markdown-it/src/options.js b/app/assets/javascripts/discourse-markdown-it/src/options.js index 272c72da816..9ab36231bab 100644 --- a/app/assets/javascripts/discourse-markdown-it/src/options.js +++ b/app/assets/javascripts/discourse-markdown-it/src/options.js @@ -10,6 +10,7 @@ export default function buildOptions(state) { lookupPrimaryUserGroup, getTopicInfo, topicId, + postId, forceQuoteLink, userId, getCurrentUser, @@ -48,6 +49,7 @@ export default function buildOptions(state) { lookupPrimaryUserGroup, getTopicInfo, topicId, + postId, forceQuoteLink, userId, getCurrentUser, diff --git a/app/assets/javascripts/discourse/tests/unit/lib/pretty-text-test.js b/app/assets/javascripts/discourse/tests/unit/lib/pretty-text-test.js index 3fc88d6008f..5641ba0c244 100644 --- a/app/assets/javascripts/discourse/tests/unit/lib/pretty-text-test.js +++ b/app/assets/javascripts/discourse/tests/unit/lib/pretty-text-test.js @@ -666,6 +666,15 @@ eviltrout

); }); + test("Heading anchors with post id", function (assert) { + assert.cookedOptions( + "# 1\n\n# one", + { postId: 1234 }, + '

1

\n' + + '

one

' + ); + }); + test("bold and italics", function (assert) { assert.cooked( 'a "**hello**"', diff --git a/app/models/post.rb b/app/models/post.rb index cbf00888fac..7b2740e0f1b 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -325,6 +325,7 @@ class Post < ActiveRecord::Base # is referencing. options[:user_id] = self.last_editor_id options[:omit_nofollow] = true if omit_nofollow? + options[:post_id] = self.id if self.should_secure_uploads? each_upload_url do |url| diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb index 0d5f9fbdcff..57968978a46 100644 --- a/lib/pretty_text.rb +++ b/lib/pretty_text.rb @@ -159,6 +159,7 @@ module PrettyText # markdown_it_rules - An array of markdown rule names which will be applied to the markdown-it engine. Currently used by plugins to customize what markdown-it rules should be # enabled when rendering markdown. # topic_id - Topic id for the post being cooked. + # post_id - Post id for the post being cooked. # user_id - User id for the post being cooked. # force_quote_link - Always create the link to the quoted topic for [quote] bbcode. Normally this only happens # if the topic_id provided is different from the [quote topic:X]. @@ -208,6 +209,7 @@ module PrettyText JS buffer << "__optInput.topicId = #{opts[:topic_id].to_i};\n" if opts[:topic_id] + buffer << "__optInput.postId = #{opts[:post_id].to_i};\n" if opts[:post_id] if opts[:force_quote_link] buffer << "__optInput.forceQuoteLink = #{opts[:force_quote_link]};\n" diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 1f78830c302..86910fa3256 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -1168,20 +1168,30 @@ RSpec.describe Post do expect(post.cooked).to match(/noopener nofollow ugc/) end - it "passes the last_editor_id as the markdown user_id option" do + it "passes the last_editor_id as the markdown user_id option and post_id" do post.save post.reload PostAnalyzer .any_instance .expects(:cook) - .with(post.raw, { cook_method: Post.cook_methods[:regular], user_id: post.last_editor_id }) + .with( + post.raw, + { + cook_method: Post.cook_methods[:regular], + user_id: post.last_editor_id, + post_id: post.id, + }, + ) post.cook(post.raw) user_editor = Fabricate(:user) post.update!(last_editor_id: user_editor.id) PostAnalyzer .any_instance .expects(:cook) - .with(post.raw, { cook_method: Post.cook_methods[:regular], user_id: user_editor.id }) + .with( + post.raw, + { cook_method: Post.cook_methods[:regular], user_id: user_editor.id, post_id: post.id }, + ) post.cook(post.raw) end