質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.60%

マークダウンを外して投稿一覧を表示する

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 459

前提・実現したいこと

Qiitaの様なナレッジベースサイトを作っています。すでに、新規のコンテンツ投稿時にマークダウン形式で入力ができる機能を実装できています。

現在、投稿の「一覧」を表示するページを製作中にて、マークダウンを外したテキストを表示させたいのですが、どう実装すれば良いのかわからず、困っています

以下の、マークダウンをつける方は、無事に実装済みです。

  • マークダウンへの変換にはmarked.jsを導入
  • 入力時のリアルタイムプレビューも実装
  • マークダウンの付いたオリジナルテキストをデータベースへ保存
  • 投稿記事の詳細ページでは、データベースから呼び出した後にhtml化して画面に表示させる

イメージ説明
イメージ説明

発生している問題・エラーメッセージ

現状は、以下の画像の通りで、マークダウンの特殊記号が付いたテキストをそのまま返しています。

イメージ説明

マークダウンを外すモジュールには、remove-markdown.jsを使用しており、jsファイルに直打ちでマークダウンの付いたテキストを入れると、マークダウンが外れた状態で表示されるので、モジュール自体は問題なく動作しています。

必要なのは、投稿の一覧を表示するviewファイルから、モジュールのコードのあるjsファイルまでテキストを投げてあげて、マークダウンを外したテキストを、再び一覧のviewファイルに戻してあげるということだと思うのですが、実装の方法がよくわかりません。

該当のソースコード

一覧を表示させるページです。 @foreach ($posts as $post)で、投稿毎にボディテキスト、タイトル、投稿日時などを表示させています。

この投稿一件ごとの処理の間( @foreach の中)で、ボディテキストを取得して、マークダウンを外す処理を入れてあげる様なイメージをしているのですが、この途中でスクリプトを書き込む(インナースクリプト?)ことは問題ないのでしょうか? 

全く別のやり方、例えば文章全体をロードした後に、全部からマークダウンを外す処理を全部にかける?とかがあるでしょうか。教えていただけると嬉しいです。

@extends('layouts.app')

@section('content')
    <div class="container mt-4">

        <div class="mb-4">
            <a href="{{ route('posts.create') }}" class="btn btn-primary">
                投稿を新規作成する
            </a>
        </div>

        @foreach ($posts as $post)
            <div class="card mb-4">
                <div class="card-header">
                    タイトル: {{ $post->title }}
                    投稿者: 
                    <a href="{{ route('users.show', ['username' => $post->user->name]) }}">
                        {{ $post->user->name }}
                    </a>
                </div>

                <div class="card-body">
                    <p class="card-text">
                        {{-- 投稿のボディテキストの一部を表示させている --}}
                        <li> {{ \Illuminate\Support\Str::limit($post->body, 140) }}
                    </p>

                    {{-- <script>
                        ここら辺で、remove-markdown.jsを呼び出しているjsファイルへテキストを投げて、結果を受け取る処理を入れるイメージでしょうか?
                    </script> --}}


                    <a class="card-link" href="{{ route('posts.show', ['post' => $post]) }}">
                        続きを読む
                    </a>
                    <p class="card-text">
                        @foreach ($post->tags as $tag) 
                            <a href="{{ route('tags.show', ['id' => $tag]) }}">
                                #{{ $tag->name }}
                            </a>
                        @endforeach 
                    </p>
                </div>

                <div class="card-footer">
                    <span class="mr-2">
                        投稿日時 {{ $post->created_at->format('Y.m.d') }}
                    </span>
                    @if ($post->comments->count())
                        <span class="badge badge-primary">
                            コメント {{ $post->comments->count() }}件
                        </span>
                    @endif
                </div>

            </div>
        @endforeach

        {{-- ページネーション --}}
        <div class="d-flex justify-content-center mb-5">
            {{ $posts->links() }}
        </div>

    </div>
@endsection


@section('javascript-footer')
  {{-- この場所に画面毎(フッタ位置)のjsを記述する --}}
@endsection

補足情報(FW/ツールのバージョンなど)

Laravel6のフレームワークを使用しています、表側はjQuery(javascript)で実装しています。マークダウンとリマークダウンでは以下のモジュールを使用しています。

どうぞよろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

いったんマークダウン記法をパーサでHTMLにした後、PHP の strip_tags() で html を取り除けば良いと思います。

https://www.php.net/manual/ja/function.strip-tags.php

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/31 23:30

    なるほど!そういう発想もあるんですね。strip_tags()知りませんでした、ありがとうございます!

    キャンセル

checkベストアンサー

+1

この投稿一件ごとの処理の間( @foreach の中)で、ボディテキストを取得して、マークダウンを外す処理を入れてあげる様なイメージをしているのですが、この途中でスクリプトを書き込む(インナースクリプト?)ことは問題ないのでしょうか?  

ビューの中でロジックをガリガリ書くのは可読性が悪くなるので
データ取得時、コントローラ内で置換しては如何でしょうか。
ただ、確かに2回回すことになるのでパフォーマンス面が気になるのは分からなくもないですが、
一覧取得だけであればそう一気に何万件も表示させるわけではないでしょうし。
(いずれにしても共通の処理関数作ることになりそうなので、ビューのループ内でその関数通すのもありと言えばあり)

teratailも20件ずつの表示ですし、何なら同じようにタイトルだけ表示にして
そもそも置換するという作業をしなくても良いようにする、、、、というのも
設計段階で考えても良いように思います。
要は「一覧で中も表示させてどれだけのメリットがあるか」というのを突き詰めることですね。
teratailは「タイトルだけでどういう要件が伝わるようにしよう」というのがガイドラインにあるので
表示させないようになってると思います。(正確には”なった”。以前は質問本文冒頭が表示されていた)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/01 18:51

    一度、解決済みとしてしまいましたが、全くできていませんでした。

    一覧表示のviewファイル(index.blade.php)の冒頭にて、一度に表示させる10件分の投稿データ($posts)をjson形式でjsファイル(jquery.plaintext.js)へ渡し、jsファイル内でマークダウンを外す処理をした後、再びviewファイルへ戻すというやり方でトライしています。コードは以下の様な形です。

    // index.blade.php
    @section('javascript-head')
    {{-- この場所に画面毎(ヘッダ位置)のjsを記述する --}}
    <script>
    const markdown = @json($posts);
    </script>
    <script src="{{ asset('js/assets/jquery.plaintext.js') }}" defer></script>
    @endsection


    //jquery.plaintext.js'
    const removeMd = require('remove-markdown'); //remove-markdown.jsの呼び出し

    // postsからpostを取り出し、bodyにremoveMdをかけて加工し、再びpostオブジェクトに戻す
    $(function () {
    const posts = markdown.data; // index.blade.phpから10件分の投稿データを受け取る
    posts.forEach(function (post) {
    post.body = removeMd(post.body);
    });
    console.log(posts);
    // ここから、index.blade.phpへ配列を戻す方法がわからない
    })

    console.log(posts);で、マークダウンを外したplain textまで戻せているんですが、ここから、index.blade.phpへ配列を戻す方法がよくわかりません・・・。

    キャンセル

  • 2020/01/01 19:40

    ひとまず「受付中」に戻しておいてください。

    キャンセル

  • 2020/01/01 20:59 編集

    すみません。teratailに質問するのも初めてなど素人なもので。「受付中」に戻す方法がわからず・・・。必要であれば、別立てで質問を投稿し直します。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る