প্রতিক্রিয়া উপাদানগুলিতে মার্কডাউনের একটি ছোট উপসেট কীভাবে পার্স করবেন?


9

আমার কাছে কিছু কাস্টম এইচটিএমএল সহ মার্কডাউনের একটি খুব ছোট উপসেট রয়েছে যা আমি প্রতিক্রিয়া উপাদানগুলিতে পার্স করতে চাই। উদাহরণস্বরূপ, আমি নিম্নলিখিত স্ট্রিংটি চালু করতে চাই:

hello *asdf* *how* _are_ you !doing! today

নিম্নলিখিত অ্যারেতে:

[ "hello ", <strong>asdf</strong>, " ", <strong>how</strong>, " ", <em>are</em>, " you ", <MyComponent onClick={this.action}>doing</MyComponent>, " today" ]

এবং তারপরে এটি একটি প্রতিক্রিয়া রেন্ডার ফাংশন থেকে ফেরান (প্রতিক্রিয়াটি বিন্যাসিত HTML হিসাবে অ্যারেটি যথাযথভাবে রেন্ডার করবে)

মূলত, আমি ব্যবহারকারীদের তাদের লেখাকে স্টাইলযুক্ত উপাদানগুলিতে পরিণত করার জন্য মার্কডাউনের একটি খুব সীমিত সেট ব্যবহার করার বিকল্পটি দিতে চাই (এবং কিছু ক্ষেত্রে আমার নিজস্ব উপাদান!)

এটি বিপজ্জনকভাবে সেটআইনার এইচটিএমএল এর পক্ষে বোকামি, এবং আমি বাহ্যিক নির্ভরতা আনতে চাই না, কারণ এগুলি সবগুলি খুব ভারী, এবং আমার কেবল খুব বেসিক কার্যকারিতা প্রয়োজন।

আমি বর্তমানে এটির মতো কিছু করছি, তবে এটি খুব ভঙ্গুর এবং সব ক্ষেত্রেই কাজ করে না। আমি ভাবছিলাম যে এর থেকে আরও ভাল উপায় যদি আছে:

function matchStrong(result, i) {
  let match = result[i].match(/(^|[^\\])\*(.*)\*/);
  if (match) { result[i] = <strong key={"ms" + i}>{match[2]}</strong>; }
  return match;
}

function matchItalics(result, i) {
  let match = result[i].match(/(^|[^\\])_(.*)_/); // Ignores \_asdf_ but not _asdf_
  if (match) { result[i] = <em key={"mi" + i}>{match[2]}</em>; }
  return match;
}

function matchCode(result, i) {
  let match = result[i].match(/(^|[^\\])```\n?([\s\S]+)\n?```/);
  if (match) { result[i] = <code key={"mc" + i}>{match[2]}</code>; }
  return match;
}

// Very brittle and inefficient
export function convertMarkdownToComponents(message) {
  let result = message.match(/(\\?([!*_`+-]{1,3})([\s\S]+?)\2)|\s|([^\\!*_`+-]+)/g);

  if (result == null) { return message; }

  for (let i = 0; i < result.length; i++) {
    if (matchCode(result, i)) { continue; }
    if (matchStrong(result, i)) { continue; }
    if (matchItalics(result, i)) { continue; }
  }

  return result;
}

এখানে আমার আগের প্রশ্নটি যা এটির দিকে পরিচালিত করেছিল।


1
ইনপুটটিতে যদি নেস্টেড আইটেম থাকে, তবে কী হবে font _italic *and bold* then only italic_ and normal? প্রত্যাশিত ফলাফল কি হবে? নাকি কখনও বাসা বাঁধবে না?
ট্রাইঙ্কট

1
বাসা বাঁধার বিষয়ে চিন্তা করার দরকার নেই। এটি ব্যবহারকারীদের ব্যবহারের জন্য খুব বুনিয়াদি মার্কডাউন। যা প্রয়োগ করা সবচেয়ে সহজ তা আমার কাছে ঠিক। আপনার উদাহরণে, যদি অভ্যন্তরীণ সাহসী কাজ না করে তবে এটি পুরোপুরি ঠিক আছে। তবে যদি এটি না থাকার চেয়ে বাসা বাঁধতে কার্যকর করা সহজ হয় তবে এটি ঠিক আছে।
রায়ান পেশেল

1
কেবলমাত্র এনপিজেজেএস
প্যাকেজ

1
যদিও আমি মার্কডাউন ব্যবহার করছি না। এটি এর একেবারেই অনুরূপ / ছোট উপসেট (এটি একটি নেস্টেড বোল্ড, ইটালিকস, কোড, আন্ডারলাইন সহ কয়েকটি কাস্টম উপাদান সমর্থন করে)। আমি স্নিপেটগুলি কিছুটা কাজ পোস্ট করেছি, তবে খুব আদর্শ বলে মনে হয় না এবং কিছু তুচ্ছ ঘটনাতেও ব্যর্থ হয় (যেমন আপনি একটির মতো অস্ট্রিককে টাইপ করতে পারবেন না: asdf*এটি অদৃশ্য না হয়ে)
রায়ান পেশেল

1
ভাল ... markdown মত markdown বা কিছু পার্স না ঠিক একটি সহজ টাস্ক আছে ... regexes, এটা কাটা না ... এইচটিএমএল সংক্রান্ত একটি অনুরূপ প্রশ্নের জন্য দেখতে stackoverflow.com/questions/1732348/...
mb21

উত্তর:


1

কিভাবে এটা কাজ করে?

এটি অংশ দ্বারা একটি স্ট্রিং অংশ পড়া দ্বারা কাজ করে, যা সত্যিই দীর্ঘ স্ট্রিংয়ের জন্য সেরা সমাধান নাও হতে পারে।

যখনই পার্সার সনাক্ত করে একটি সমালোচনামূলক অংশটি পড়া হচ্ছে, অর্থাৎ '*'বা অন্য কোনও মার্কডাউন ট্যাগ পড়া হচ্ছে, যখনই পার্সার তার সমাপনী ট্যাগটি খুঁজে না পায় ততক্ষণ এই উপাদানটির অংশগুলি পার্স করা শুরু করে।

এটি মাল্টি-লাইন স্ট্রিংয়ে কাজ করে, উদাহরণস্বরূপ কোডটি দেখুন।

আদেশ সহকারে

আপনি নির্দিষ্ট করেন নি, বা আমি আপনার প্রয়োজনগুলি ভুল বোঝাবুঝি করতে পারি, যদি এমন দু'টি গা .় এবং তির্যক হয় এমন ট্যাগগুলি বিশ্লেষণের প্রয়োজনীয়তা থাকে তবে আমার বর্তমান সমাধানটি এই ক্ষেত্রে নাও কাজ করতে পারে।

আপনার যদি প্রয়োজন হয় তবে উপরের শর্তগুলি নিয়ে কাজ করার জন্য এখানে কেবলমাত্র মন্তব্য করুন এবং আমি কোডটি টুইট করব।

প্রথম আপডেট: মার্কডাউন ট্যাগগুলি কীভাবে চিকিত্সা করা হবে তা টুইট করে

ট্যাগগুলি আর হার্ডকোডযুক্ত নয়, পরিবর্তে এগুলি একটি মানচিত্র যেখানে আপনি সহজেই আপনার প্রয়োজনীয়তার সাথে মানিয়ে নিতে পারেন extend

আপনি মন্তব্যগুলিতে উল্লিখিত বাগগুলি স্থির করেছেন, এই সমস্যাগুলি দেখানোর জন্য ধন্যবাদ = পি

দ্বিতীয় আপডেট: বহু দৈর্ঘ্যের মার্কডাউন ট্যাগ

এটি অর্জনের সবচেয়ে সহজ উপায়: খুব কম ব্যবহৃত ইউনিকোডের সাথে বহু-দৈর্ঘ্যের চরগুলি প্রতিস্থাপন

যদিও পদ্ধতিটি parseMarkdownএখনও বহু-দৈর্ঘ্যের ট্যাগগুলিকে সমর্থন করে না, আমরা string.replace আমাদের rawMarkdownপ্রপটি প্রেরণ করার সময় আমরা সহজেই সেই বহু-দৈর্ঘ্যের ট্যাগগুলিকে সরল সাথে প্রতিস্থাপন করতে পারি ।

বাস্তবে এর উদাহরণ দেখতে ReactDOM.renderকোডের শেষে অবস্থিত এটিকে দেখুন ।

এমনকি যদি আপনার আবেদন করে সমর্থন একাধিক ভাষা, সেখানে অবৈধ ইউনিকোড অক্ষর জাভাস্ক্রিপ্ট এখনো সনাক্ত প্রাক্তন .: হয় "\uFFFF"একটি বৈধ ইউনিকোড, আমি যদি সঠিকভাবে প্রত্যাহার, কিন্তু জাতীয় এখনও এটি তুলনা করতে সক্ষম হবে ( "\uFFFF" === "\uFFFF" = true)

এটি প্রথমে হ্যাক-ই মনে হতে পারে তবে আপনার ব্যবহারের উপর নির্ভর করে আমি এই রুটটি ব্যবহার করে কোনও বড় সমস্যা দেখছি না।

এটি অর্জনের আর একটি উপায়

ঠিক আছে, আমরা সহজেই শেষটি ট্র্যাক করতে পারি N(যেখানে Nদীর্ঘতম বহু দৈর্ঘ্যের ট্যাগের দৈর্ঘ্যের সাথে মিল রয়েছে) খণ্ডগুলি।

অভ্যন্তরীণ পদ্ধতিটির লুপটি যেভাবে parseMarkdownআচরণ করে তার জন্য কিছু টুইট করতে হবে , যেমন বর্তমান খণ্ডটি কোনও বহু-দৈর্ঘ্যের ট্যাগের অংশ কিনা তা পরীক্ষা করা হয়, যদি এটি ট্যাগ হিসাবে এটি ব্যবহার করা হয়; অন্যথায়, এর মতো ক্ষেত্রে ``kআমাদের এটিকে notMultiLengthবা অনুরূপ কিছু হিসাবে চিহ্নিত করা এবং সেই অংশটিকে বিষয়বস্তু হিসাবে চাপানো দরকার।

কোড

// Instead of creating hardcoded variables, we can make the code more extendable
// by storing all the possible tags we'll work with in a Map. Thus, creating
// more tags will not require additional logic in our code.
const tags = new Map(Object.entries({
  "*": "strong", // bold
  "!": "button", // action
  "_": "em", // emphasis
  "\uFFFF": "pre", // Just use a very unlikely to happen unicode character,
                   // We'll replace our multi-length symbols with that one.
}));
// Might be useful if we need to discover the symbol of a tag
const tagSymbols = new Map();
tags.forEach((v, k) => { tagSymbols.set(v, k ); })

const rawMarkdown = `
  This must be *bold*,

  This also must be *bo_ld*,

  this _entire block must be
  emphasized even if it's comprised of multiple lines_,

  This is an !action! it should be a button,

  \`\`\`
beep, boop, this is code
  \`\`\`

  This is an asterisk\\*
`;

class App extends React.Component {
  parseMarkdown(source) {
    let currentTag = "";
    let currentContent = "";

    const parsedMarkdown = [];

    // We create this variable to track possible escape characters, eg. "\"
    let before = "";

    const pushContent = (
      content,
      tagValue,
      props,
    ) => {
      let children = undefined;

      // There's the need to parse for empty lines
      if (content.indexOf("\n\n") >= 0) {
        let before = "";
        const contentJSX = [];

        let chunk = "";
        for (let i = 0; i < content.length; i++) {
          if (i !== 0) before = content[i - 1];

          chunk += content[i];

          if (before === "\n" && content[i] === "\n") {
            contentJSX.push(chunk);
            contentJSX.push(<br />);
            chunk = "";
          }

          if (chunk !== "" && i === content.length - 1) {
            contentJSX.push(chunk);
          }
        }

        children = contentJSX;
      } else {
        children = [content];
      }
      parsedMarkdown.push(React.createElement(tagValue, props, children))
    };

    for (let i = 0; i < source.length; i++) {
      const chunk = source[i];
      if (i !== 0) {
        before = source[i - 1];
      }

      // Does our current chunk needs to be treated as a escaped char?
      const escaped = before === "\\";

      // Detect if we need to start/finish parsing our tags

      // We are not parsing anything, however, that could change at current
      // chunk
      if (currentTag === "" && escaped === false) {
        // If our tags array has the chunk, this means a markdown tag has
        // just been found. We'll change our current state to reflect this.
        if (tags.has(chunk)) {
          currentTag = tags.get(chunk);

          // We have simple content to push
          if (currentContent !== "") {
            pushContent(currentContent, "span");
          }

          currentContent = "";
        }
      } else if (currentTag !== "" && escaped === false) {
        // We'll look if we can finish parsing our tag
        if (tags.has(chunk)) {
          const symbolValue = tags.get(chunk);

          // Just because the current chunk is a symbol it doesn't mean we
          // can already finish our currentTag.
          //
          // We'll need to see if the symbol's value corresponds to the
          // value of our currentTag. In case it does, we'll finish parsing it.
          if (symbolValue === currentTag) {
            pushContent(
              currentContent,
              currentTag,
              undefined, // you could pass props here
            );

            currentTag = "";
            currentContent = "";
          }
        }
      }

      // Increment our currentContent
      //
      // Ideally, we don't want our rendered markdown to contain any '\'
      // or undesired '*' or '_' or '!'.
      //
      // Users can still escape '*', '_', '!' by prefixing them with '\'
      if (tags.has(chunk) === false || escaped) {
        if (chunk !== "\\" || escaped) {
          currentContent += chunk;
        }
      }

      // In case an erroneous, i.e. unfinished tag, is present and the we've
      // reached the end of our source (rawMarkdown), we want to make sure
      // all our currentContent is pushed as a simple string
      if (currentContent !== "" && i === source.length - 1) {
        pushContent(
          currentContent,
          "span",
          undefined,
        );
      }
    }

    return parsedMarkdown;
  }

  render() {
    return (
      <div className="App">
        <div>{this.parseMarkdown(this.props.rawMarkdown)}</div>
      </div>
    );
  }
}

ReactDOM.render(<App rawMarkdown={rawMarkdown.replace(/```/g, "\uFFFF")} />, document.getElementById('app'));

কোডের সাথে লিখিত (টাইপস্ক্রিপ্ট) https://codepen.io/ludanin/pen/GRgNWPv

কোডটির সাথে লিঙ্ক করুন (ভ্যানিলা / ব্যাবেল) https://codepen.io/ludanin/pen/eYmBvXw


আমি মনে করি এই সমাধানটি সঠিক পথে রয়েছে তবে মনে হয় এটি অন্য চিহ্নের মধ্যে অন্যান্য মার্কডাউন চরিত্রগুলি রেখে সমস্যা রয়েছে। উদাহরণস্বরূপ, এর This must be *bold*সাথে প্রতিস্থাপনের চেষ্টা করুন This must be *bo_ld*। এটি ফলস্বরূপ এইচটিএমএলকে
ত্রুটিযুক্ত করে

সঠিক পরীক্ষার অভাবে এই = পি উত্পাদিত হয়েছে, আমার খারাপ। আমি ইতিমধ্যে এটি ঠিক করে দিচ্ছি এবং ফলাফলটি এখানে পোস্ট করতে যাচ্ছি, এটি ঠিক করার মতো একটি সাধারণ সমস্যা বলে মনে হচ্ছে।
লুকাশ ড্যানিন

হ্যাঁ ধন্যবাদ. যদিও আমি সত্যিই এই সমাধানটি পছন্দ করি। এটি খুব মজবুত এবং পরিষ্কার বলে মনে হচ্ছে। আমি মনে করি এটি আরও কিছুটা কমনীয়তার জন্য কিছুটা হলেও রিফেক্টর করা যায়। আমি এটির সাথে কিছুটা গোলযোগের চেষ্টা করব।
রায়ান পেশেল

সম্পন্ন, যাইহোক, আমি মার্কডাউন ট্যাগগুলি এবং তাদের সংশ্লিষ্ট জেএসএক্স মানগুলি সংজ্ঞায়নের আরও নমনীয় উপায়ে সমর্থন করার জন্য কোডটি টুইট করেছি।
লুকাশ ড্যানিন

আরে ধন্যবাদ এই দুর্দান্ত লাগছে। কেবল একটি শেষ জিনিস এবং আমি মনে করি এটি নিখুঁত হবে। আমার মূল পোস্টে আমার কাছে কোড স্নিপেটের জন্যও একটি ফাংশন রয়েছে (এতে ট্রিপল ব্যাকটিকস জড়িত)। এটির পক্ষেও সমর্থন পাওয়া কি সম্ভব? যাতে ট্যাগগুলি allyচ্ছিকভাবে একাধিক অক্ষর হতে পারে? আর একটি উত্তর খুব কম ব্যবহৃত চরিত্রের সাথে `` of এর উদাহরণগুলি প্রতিস্থাপন করে সমর্থন যোগ করেছে। এটি করার সহজ উপায় হ'ল, তবে নিশ্চিত না যে এটি আদর্শ if
রায়ান পেশেল

4

দেখে মনে হচ্ছে আপনি খুব ছোট একটি মৌলিক সমাধান খুঁজছেন। "সুপার-দানব" এর মতো নয় react-markdown-it:)

আমি আপনাকে https://github.com/developit/snarkdown সুপারিশ করতে চাই যা দেখতে বেশ হালকা ওজনের এবং সুন্দর! মাত্র 1 কেবি এবং অত্যন্ত সহজ, আপনি যদি অন্য কোনও সিনট্যাক্স বৈশিষ্ট্য প্রয়োজন তবে আপনি এটি ব্যবহার করতে এবং এটি প্রসারিত করতে পারেন।

সমর্থিত ট্যাগগুলির তালিকা https://github.com/developit/snarkdown/blob/master/src/index.js#L1

হালনাগাদ

প্রতিক্রিয়ার উপাদানগুলি সম্পর্কে সবেমাত্র লক্ষ্য করা গেছে, শুরুতে এটি মিস করেছেন। সুতরাং এটি আপনার পক্ষে দুর্দান্ত যে আমি এইচটিএমএলকে বিপজ্জনকভাবে সেট না করেই লাইব্রেরিকে একটি উদাহরণ হিসাবে গ্রহণ করেছি এবং এটি আপনার কাস্টম প্রয়োজনীয় উপাদানগুলি বাস্তবায়িত করতে বিশ্বাস করি। গ্রন্থাগারটি বেশ ছোট এবং পরিষ্কার। এটি দিয়ে মজা করুন! :)


3
var table = {
  "*":{
    "begin":"<strong>",
    "end":"</strong>"
    },
  "_":{
    "begin":"<em>",
    "end":"</em>"
    },
  "!":{
    "begin":"<MyComponent onClick={this.action}>",
    "end":"</MyComponent>"
    },

  };

var myMarkdown = "hello *asdf* *how* _are_ you !doing! today";
var tagFinder = /(?<item>(?<tag_begin>[*|!|_])(?<content>\w+)(?<tag_end>\k<tag_begin>))/gm;

//Use case 1: direct string replacement
var replaced = myMarkdown.replace(tagFinder, replacer);
function replacer(match, whole, tag_begin, content, tag_end, offset, string) {
  return table[tag_begin]["begin"] + content + table[tag_begin]["end"];
}
alert(replaced);

//Use case 2: React components
var pieces = [];
var lastMatchedPosition = 0;
myMarkdown.replace(tagFinder, breaker);
function breaker(match, whole, tag_begin, content, tag_end, offset, string) {
  var piece;
  if (lastMatchedPosition < offset)
  {
    piece = string.substring(lastMatchedPosition, offset);
    pieces.push("\"" + piece + "\"");
  }
  piece = table[tag_begin]["begin"] + content + table[tag_begin]["end"];
  pieces.push(piece);
  lastMatchedPosition = offset + match.length;

}
alert(pieces);

ফলাফল: চলমান ফলাফল

রেজেজএক্স পরীক্ষার ফলাফল

ব্যাখ্যা:

/(?<item>(?<tag_begin>[*|!|_])(?<content>\w+)(?<tag_end>\k<tag_begin>))/
  • আপনি এই বিভাগে আপনার ট্যাগগুলি সংজ্ঞায়িত করতে পারেন: তার মধ্যে [*|!|_]একবারের সাথে একটি মিলে গেলে, এটি একটি গোষ্ঠী হিসাবে ক্যাপচার হবে এবং নাম হিসাবে "ট্যাগ_বেগিন" হবে।

  • এবং তারপরে (?<content>\w+)ট্যাগটি মোড়ানো সামগ্রী ক্যাপচার করে।

  • শেষের ট্যাগটি অবশ্যই আগের ম্যাচের মতো একই হওয়া উচিত, তাই এখানে ব্যবহার করে \k<tag_begin>এবং যদি এটি পরীক্ষায় উত্তীর্ণ হয় তবে এটি একটি গোষ্ঠী হিসাবে ক্যাপচার করুন এবং একটি নাম "ট্যাগ_েন্ড" দিন, (?<tag_end>\k<tag_begin>))এটিই বলছে।

জেএসে আপনি এর মতো একটি টেবিল সেট আপ করেছেন:

var table = {
  "*":{
    "begin":"<strong>",
    "end":"</strong>"
    },
  "_":{
    "begin":"<em>",
    "end":"</em>"
    },
  "!":{
    "begin":"<MyComponent onClick={this.action}>",
    "end":"</MyComponent>"
    },

  };

মেলা ট্যাগগুলি প্রতিস্থাপন করতে এই টেবিলটি ব্যবহার করুন।

স্টিং.রেপ্লেসের একটি ওভারলোড স্ট্রিং.রেপ্লেস (রেজিএক্সপ্লেস, ফাংশন) রয়েছে যা ক্যাপচার গ্রুপকে প্যারামিটার হিসাবে নিতে পারে, আমরা এই ক্যাপচার আইটেমগুলি টেবিলটি সন্ধান করার জন্য ব্যবহার করি এবং প্রতিস্থাপনের স্ট্রিং তৈরি করি।

[আপডেট]
আমি কোডটি আপডেট করেছি, অন্য কারও প্রতিক্রিয়াশীল উপাদানগুলির প্রয়োজন না হলে আমি প্রথমটি রেখেছি এবং আপনি দেখতে পাচ্ছেন যে তাদের মধ্যে সামান্য পার্থক্য রয়েছে। উপাদান প্রতিক্রিয়া


দুর্ভাগ্যক্রমে আমি নিশ্চিত না যে এটি কাজ করে কিনা। কারণ আমার নিজের প্রকৃত প্রতিক্রিয়া উপাদান এবং উপাদানগুলি নিজের প্রয়োজন, সেগুলির স্ট্রিং নয়। আপনি যদি আমার আসল পোস্টটিতে সন্ধান করেন তবে আপনি দেখতে পাবেন যে আমি প্রকৃত উপাদানগুলিকে একটি অ্যারেতে যুক্ত করছি, সেগুলির স্ট্রিং নয়। এবং বিপজ্জনকভাবে সেটআইনার এইচটিএমএল ব্যবহার করা বিপজ্জনক কারণ ব্যবহারকারী দূষিত স্ট্রিংগুলি ইনপুট করতে পারে।
রায়ান পেশেল 10'19

ভাগ্যক্রমে স্ট্রিং প্রতিস্থাপনটিকে প্রতিক্রিয়া উপাদানগুলিতে রূপান্তর করা খুব সহজ, আমি কোডটি আপডেট করেছি।
সাইমন

হুঁ? আমি অবশ্যই কিছু মিস করছি, কারণ তারা এখনও আমার শেষ প্রান্তে রয়েছে। এমনকি আমি আপনার কোড দিয়ে একটি বেহুদা তৈরি করেছি। আপনি যদি console.logআউটপুটটি পড়েন তবে দেখবেন অ্যারেটি স্ট্রিংয়ে পূর্ণ, বাস্তবের
রায়ান

সত্যই আমি প্রতিক্রিয়া জানিনা, তাই আমি আপনার প্রয়োজন অনুসারে সবকিছু ঠিকঠাক তৈরি করতে পারি না, তবে আমি মনে করি আপনার প্রশ্নটি কীভাবে সমাধান করবেন সে সম্পর্কিত তথ্য যথেষ্ট, আপনার সেগুলি আপনার প্রতিক্রিয়া মেশিনে রাখা দরকার এবং এটি কেবল যেতে পারে।
সাইমন

এই থ্রেডটি বিদ্যমান থাকার কারণ হ'ল প্রতিক্রিয়ার উপাদানগুলিতে তাদের পার্স করা উল্লেখযোগ্যভাবে শক্ত বলে মনে হচ্ছে (সুতরাং থ্রেড শিরোনাম যে সঠিক প্রয়োজনটি উল্লেখ করে)। তাদের স্ট্রিংগুলিতে পার্স করা মোটামুটি তুচ্ছ এবং আপনি কেবল স্ট্রিং প্রতিস্থাপন ফাংশনটি ব্যবহার করতে পারেন। স্ট্রিংগুলি আদর্শ সমাধান নয় কারণ তারা বিপজ্জনকভাবে
সেটিংআইএনএইচটিএমএল

0

আপনি এটি এইভাবে করতে পারেন:

//inside your compoenet

   mapData(myMarkdown){
    return myMarkdown.split(' ').map((w)=>{

        if(w.startsWith('*') && w.endsWith('*') && w.length>=3){
           w=w.substr(1,w.length-2);
           w=<strong>{w}</strong>;
         }else{
             if(w.startsWith('_') && w.endsWith('_') && w.length>=3){
                w=w.substr(1,w.length-2);
                w=<em>{w}</em>;
              }else{
                if(w.startsWith('!') && w.endsWith('!') && w.length>=3){
                w=w.substr(1,w.length-2);
                w=<YourComponent onClick={this.action}>{w}</YourComponent>;
                }
            }
         }
       return w;
    })

}


 render(){
   let content=this.mapData('hello *asdf* *how* _are_ you !doing! today');
    return {content};
  }

0

A working solution purely using Javascript and ReactJs without dangerouslySetInnerHTML.

অভিগমন

চিহ্নডাউন উপাদানগুলির জন্য অক্ষর অনুসন্ধান দ্বারা অক্ষর। যত তাড়াতাড়ি একটি মুখোমুখি হয়, একই জন্য শেষ ট্যাগটি অনুসন্ধান করুন এবং তারপরে এটি এইচটিএমএলে রূপান্তর করুন।

স্নিপেটে ট্যাগগুলি সমর্থিত

  • সাহসী
  • তির্যক
  • ই.এম.
  • প্রাক

স্নিপেট থেকে ইনপুট এবং আউটপুট:

জেএসফিডাল: https://jsfiddle.net/sunil12738/wg7emcz1/58/

কোড:

const preTag = "đ"
const map = {
      "*": "b",
      "!": "i",
      "_": "em",
      [preTag]: "pre"
    }

class App extends React.Component {
    constructor(){
      super()
      this.getData = this.getData.bind(this)
    }

    state = {
      data: []
    }
    getData() {
      let str = document.getElementById("ta1").value
      //If any tag contains more than one char, replace it with some char which is less frequently used and use it
      str = str.replace(/```/gi, preTag)
      const tempArr = []
      const tagsArr = Object.keys(map)
      let strIndexOf = 0;
      for (let i = 0; i < str.length; ++i) {
        strIndexOf = tagsArr.indexOf(str[i])
        if (strIndexOf >= 0 && str[i-1] !== "\\") {
          tempArr.push(str.substring(0, i).split("\\").join("").split(preTag).join(""))
          str = str.substr(i + 1);
          i = 0;
          for (let j = 0; j < str.length; ++j) {
            strIndexOf = tagsArr.indexOf(str[j])
            if (strIndexOf >= 0 && str[j-1] !== "\\") {
              const Tag = map[str[j]];
              tempArr.push(<Tag>{str.substring(0, j).split("\\").join("")}</Tag>)
              str = str.substr(j + 1);
              i = 0;
              break
             }
          }
        }
      }
      tempArr.push(str.split("\\").join(""))
      this.setState({
        data: tempArr,
      })
    }
    render() {
      return (
        <div>
          <textarea rows = "10"
            cols = "40"
           id = "ta1"
          /><br/>
          <button onClick={this.getData}>Render it</button><br/> 
          {this.state.data.map(x => x)} 
        </div>
      )
    }
  }

ReactDOM.render(
  <App/>,
  document.getElementById('root')
);
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.production.min.js"></script>
  <div id="root"></div>
</body>

বিস্তারিত ব্যাখ্যা (উদাহরণ সহ):

মনে করুন স্ট্রিংটি যদি How are *you* doing? ট্যাগগুলিতে চিহ্নগুলির জন্য ম্যাপিং রাখে Keep

map = {
 "*": "b"
}
  • আপনি প্রথম * না পাওয়া পর্যন্ত লুপ করুন, তার আগে পাঠ্যটি স্বাভাবিক স্ট্রিং
  • অ্যারের ভিতরে যে ধাক্কা। অ্যারে হয়ে উঠুন ["How are "]এবং আপনি পরবর্তী * না পাওয়া পর্যন্ত অভ্যন্তরীণ লুপটি শুরু করুন।
  • Now next between * and * needs to be bold, আমরা তাদের পাঠ্যের মাধ্যমে এইচটিএমএল উপাদানগুলিতে রূপান্তর করি এবং ম্যাপ থেকে ট্যাগ = খ যেখানে সরাসরি অ্যারেতে ঠেলাঠেলি করি। আপনি যদি করেন তবে <Tag>text</Tag>অভ্যন্তরীণভাবে প্রতিক্রিয়া পাঠ্যে রূপান্তরিত হয় এবং অ্যারেতে ধাক্কা দেয়। অ্যারে এখন ["কেমন আছেন", আপনি ]। অভ্যন্তরীণ লুপ থেকে বিরতি
  • এখন আমরা সেখান থেকে বাইরের লুপটি শুরু করি এবং কোনও ট্যাগ খুঁজে পাওয়া যায় না, তাই অ্যারেতে অবশিষ্ট থাকুন। অ্যারে পরিণত হয়: ["কেমন আছেন", আপনি , "করছেন"]।
  • ইউআইতে রেন্ডার করুন How are <b>you</b> doing?
    Note: <b>you</b> is html and not text

দ্রষ্টব্য : বাসা বাঁধাই সম্ভব। আমাদের পুনরাবৃত্তি উপরের যুক্তি কল করতে হবে

নতুন ট্যাগ সমর্থন যোগ করতে

  • যদি সেগুলি * বা! এর মতো একটি চরিত্র হয় তবে mapএটিকে অক্ষরের মতো কী এবং বস্তুটি সম্পর্কিত ট্যাগ হিসাবে মান হিসাবে যুক্ত করুন
  • যদি এগুলি than `as এর মতো একাধিক চরিত্রের হয় তবে কিছুটা ঘন ঘন ব্যবহৃত চর ব্যবহার করে একের পর এক মানচিত্র তৈরি করুন এবং তারপরে সন্নিবেশ করুন (কারণ: বর্তমানে অক্ষর অনুসন্ধানের ভিত্তিতে চরিত্রের উপর ভিত্তি করে পন্থা এবং তাই একাধিক চর বিচ্ছিন্ন হবে However , এটি যুক্তি উন্নত করেও যত্ন নেওয়া যেতে পারে)

এটি বাসা বাঁধতে সহায়তা করে? না
এটি ওপি দ্বারা উল্লিখিত সমস্ত ব্যবহারের ক্ষেত্রে সমর্থন করে? হ্যাঁ

আশা করি এটা সাহায্য করবে.


হাই, এখন এই খুঁজছেন। ট্রিপল ব্যাকটিক সমর্থন পাশাপাশি কি এটি ব্যবহার করা সম্ভব? সুতরাং কোড ব্লকগুলির জন্য `` `सादf``` পাশাপাশি কাজ করবে?
রায়ান পেশেল

এটি কিন্তু কিছু পরিবর্তন প্রয়োজন হতে পারে। বর্তমানে কেবলমাত্র একক চরিত্রের মিল রয়েছে * বা! এটিকে কিছুটা সংশোধন করা দরকার। কোড ব্লকগুলি মূলত অন্ধকার ব্যাকগ্রাউন্ডের সাথে asdfরেন্ডার হবে <pre>asdf</pre>, তাই না? আমাকে এটি জানাতে এবং আমি দেখতে পাবেন। এমনকি আপনি এখন চেষ্টা করতে পারেন। একটি সহজ পদ্ধিতি হল: উপরের সমাধানে, পাঠ্যের `` `বিশেষ অক্ষর যেমন ^ বা ~ এর সাথে প্রতিস্থাপন করুন এবং এটি প্রাক ট্যাগটিতে মানচিত্র করুন। তাহলে এটি ঠিকঠাক কাজ করবে। অন্যান্য পদ্ধতির আরও কিছু কাজ দরকার
সুনীল চৌধুরী চৌধুরী

হ্যাঁ, ঠিক, এর সাথে `` `এসিডেফ``` প্রতিস্থাপন <pre>asdf</pre>। ধন্যবাদ!
রায়ান পেশেল

@ রায়ানপেসেল হাই! preপাশাপাশি ট্যাগ সমর্থন যোগ করেছেন । এটি যদি কাজ করে তা আমাকে জানান
সুনীল চৌধুরী চৌধুরী

আকর্ষণীয় সমাধান (বিরল চরিত্রটি ব্যবহার করে)। যদিও আমি এখনও দেখতে পাচ্ছি যে পলায়নের পক্ষে সমর্থনের অভাব (যেমন \ * এসডিএফ * সাহসী নয়), যা আমি আমার মূল পোস্টে কোডটির জন্য সমর্থনটি অন্তর্ভুক্ত করেছি (এটির শেষে আমার লিঙ্কযুক্ত বিবরণেও এটি উল্লেখ করেছি) পোস্ট)। যে যোগ করা খুব কঠিন হবে?
রায়ান পেশেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.