Làm cách nào để đồng bộ hóa tài liệu với Trang Github?


81

Tôi có một dự án cùng với một số người và chúng tôi có một README.mdtệp với một loạt các GitHub Flavored Markdown được hiển thị trên trang GitHub của chúng tôi. Chúng tôi cũng thiết lập một chi nhánh GitHub Pages được lưu trữ dưới tên miền phụ của Tổ chức GitHub của chúng tôi và sử dụng Trình tạo trang tự động chỉ cần tải vào README.mdtệp của chúng tôi khi chúng tôi tạo trang của mình. Tuy nhiên, tôi nhận thấy rằng khi tôi cập nhật README.mdtệp của chúng tôi , nó không cập nhật trang dự án. Thay vào đó, chúng tôi phải chuyển đến tab cài đặt GitHub và tạo lại trang dự án, tải lại README.mdtệp khi chúng tôi thực hiện.

Ngoài ra, sau khi đọc về liên kết tương đối hoạt động giữa các tệp tài liệu trên các trang thư mục dự án GitHub. Tôi rất thích đánh dấu vì nó tiết kiệm rất nhiều thời gian khỏi việc phải viết tất cả HTML bằng tay cho tài liệu của chúng tôi. Tuy nhiên, điều tôi muốn là có thể có một README.mdtệp có thể bao gồm các liên kết tương đối đến các tệp tài liệu khác được đặt tại docs/*.md. Tôi hy vọng có một giải pháp dễ dàng để các tệp tài liệu khác của tôi cũng có thể được đưa vào nhánh gh-pages của tôi và được lưu trữ dưới tên miền phụ GitHub Pages của tôi và được hiển thị và / hoặc theo chủ đề.

Nói cách khác, câu hỏi của tôi là:

  • Có cách nào để tệp README.md của tôi tự động cập nhật trên miền phụ Trang Github của tôi không?
    • [EDIT]: Không có vẻ là câu trả lời nếu sử dụng Trình tạo trang tự động. Bạn phải truy cập trang cài đặt cho repo và tải lại nó mỗi khi có thay đổi để cập nhật nó.
       
  • Có cách nào để tôi có thể để các liên kết tương đối đến tài liệu của tôi trên tệp README.md của tôi hoạt động trên các Trang Github của tôi, có lẽ bằng cách nào đó tôi đồng bộ hóa của tôi /docs/*.mdvới các Trang Github và bằng cách nào đó hiển thị và / hoặc đặt chúng?
    • [EDIT]: Từ những gì tôi đã học được kể từ khi viết câu hỏi này, có vẻ như điều này chỉ có thể thực hiện được trên các trang GitHub thông qua việc sử dụng trình tạo trang web tĩnh như viên ngọc ruby Jekyll và có thể là một số cách sử dụng webhook được GitHub hỗ trợ đã được đề cập trong phần bình luận bên dưới. Tôi hiện đang cố gắng tìm ra một giải pháp tối ưu.
       
  • Tốt hơn nữa, có cách nào dễ dàng hơn để tôi có thể làm điều này và có lẽ chỉ có một bản sao README.md và tài liệu của tôi được sử dụng trên cả trang gh và chi nhánh chính của tôi và giúp mọi thứ dễ dàng nhất?
    • [EDIT]: Có vẻ như điều này gần như chắc chắn là không. Tôi đã suy nghĩ về khả năng có thứ gì đó được tích hợp vào GitHub để cho phép điều này. Có vẻ như hỗ trợ tốt hơn cho loại thứ này có thể được tích hợp vào Trang GitHub trong tương lai, hoặc ít nhất tôi chắc chắn hy vọng nó sẽ như vậy.
       

3
GitHub có hỗ trợ webhook sau khi nhận. Bạn đã nghĩ đến việc thêm một hook gọi một số tập lệnh từ xa để đẩy README.mdphiên bản mới vào các trang GitHub chưa?
ubik,

7
Cảm ơn vì đã tuyệt vời và chỉnh sửa những phát hiện của bạn. Không có đủ người làm điều đó trên trang web này.
Matt Kantor

Đối với câu hỏi đầu tiên, đây là một cách tiếp cận thủ công , không phải tự động, nhưng nó đơn giản và hoạt động. Đối với phần tạo HTML, người ta có thể sử dụng dillinger.io . Tôi cũng đã tìm thấy phương pháp tự động này , mặc dù tôi đã thử nhưng không hiệu quả.
iled

1
GitHub vừa cho phép sử dụng bất kỳ nhánh và thư mục nào làm nguồn cho các tài liệu . Bạn không còn phải sử dụng gh-pages.
Dan Dascalescu

Câu trả lời:


37

Tôi sẽ đăng một giải pháp mà tôi thiết lập tận dụng thực tế là Trang GitHub sử dụng Jekyll đã sử dụng Trình tạo trang tự động.

  1. git checkout gh-pages
  2. mkdir _layouts
  3. mv index.html _layouts
  4. git checkout master -- README.md
  5. mv README.md index.md
  6. Thêm văn bản sau vào index.md

 

---
layout: index
---

Bạn cũng cần mở index.htmltệp và thực hiện các thay đổi sau:

  1. Xóa HTML được hiển thị khỏi phần đánh dấu trong README.mdtệp của bạn . Đây thường là giữa <section>hoặc <article>các thẻ. Thay thế HTML này bằng văn bản, {{ content }}điều này sẽ cho phép chúng tôi sử dụng tệp này như một jekyll. Tệp mà chúng tôi áp dụng bố cục sẽ được đặt ở vị trí của thẻ nội dung.

  2. Tìm CSS cho chủ đề trang dự án của bạn. đối với tôi đây là một dòng như sau:

    <link rel='stylesheet' href='stylesheets/stylesheet.css' />

    Điều này cần được thay đổi thành

    <link rel='stylesheet' href='{{ site.path }}/stylesheets/stylesheet.css' />

  3. Bất kỳ nội dung nào khác được lưu trữ trên trang web của bạn sẽ được sử dụng trong bố cục này cũng sẽ cần có tiền tố {{ site.path }}.

Bằng cách này, Jekyll sẽ hiển thị tệp đánh dấu dưới dạng nội dung của index.htmlbố cục trong _layoutsthư mục. Để tự động hóa quá trình này không chỉ cho tệp README.md mà còn cho các tài liệu khác mà bạn có thể có trong nhánh chính của mình, tôi đã thực hiện các bước sau:

Đã tạo tệp post-commitcó tên chứa các tệp sau:

 

#!/bin/bash
###
### The following block runs after commit to "master" branch
###
if [ `git rev-parse --abbrev-ref HEAD` == "master" ]; then

    # Layout prefix is prepended to each markdown file synced
    ###################################################################
    LAYOUT_PREFIX='---\r\nlayout: index\r\n---\r\n\r\n'

    # Switch to gh-pages branch to sync it with master
    ###################################################################
    git checkout gh-pages

    # Sync the README.md in master to index.md adding jekyll header
    ###################################################################
    git checkout master -- README.md
    echo -e $LAYOUT_PREFIX > index.md
    cat README.md >> index.md
    rm README.md
    git add index.md
    git commit -a -m "Sync README.md in master branch to index.md in gh-pages"

    # Sync the markdown files in the docs/* directory
    ###################################################################
    git checkout master -- docs
    FILES=docs/*
    for file in $FILES
    do
        echo -e $LAYOUT_PREFIX | cat - "$file" > temp && mv temp "$file"
    done

    git add docs
    git commit -a -m "Sync docs from master branch to docs gh-pages directory"

    # Uncomment the following push if you want to auto push to
    # the gh-pages branch whenever you commit to master locally.
    # This is a little extreme. Use with care!
    ###################################################################
    # git push origin gh-pages

    # Finally, switch back to the master branch and exit block
    git checkout master
fi

CHỈNH SỬA: Tôi đã cập nhật tập lệnh trên cho cả README.mdtệp và dấu docs/*xuống để cả hai sử dụng cùng một tệp bố cục. Đây là một thiết lập tốt hơn nhiều so với những gì tôi đã có trước đây. Tập lệnh này có trong .git/hooks/thư mục của bạn . bash phải có trong đường dẫn của bạn.

Tạo tệp _config.ymlvới phần sau

markdown: redcarpet
path: http://username.github.io/reponame

Tập lệnh trên cũng đồng bộ hóa các tệp đánh dấu được tìm thấy trong docs/*thư mục của masternhánh, để chúng cũng có thể được xem trên trang GitHub Pages. Liên kết tương đối đến các tài liệu này hoạt động nếu bạn bao gồm hàm jQuery sau để tách .mdphần mở rộng khỏi các neo trên gh-pagesnhánh. Bạn có thể thêm tập lệnh sau index.htmlvào _layoutsthư mục:

$(document).on('ready', function () {
    $('a').each(function (i, e) {
        var href = e.href;
        if (href.search('.md') > 0)
            $(this).attr('href', href.split('.md')[0]);
    });
});

CHỈNH SỬA: Tôi đã thay đổi mã ở trên trong kho lưu trữ của mình, đây là một cách nhanh chóng và tiện lợi để thực hiện việc này, nhưng nó sẽ không hoạt động đúng trong mọi trường hợp nếu bạn hiểu ý tôi .. Ví dụ: tệp đánh dấu company.mdata.mdsẽ không được xử lý một cách chính xác. Để khắc phục điều này, tôi đã cập nhật điều này thành tập lệnh sau để kiểm tra cẩn thận hơn href và xóa phần mở rộng nếu tìm thấy. Tôi cũng làm cho tập lệnh chung chung hơn, cho phép nó được sử dụng để loại bỏ các phần mở rộng khác bằng cách thay đổi extbiến. Đây là mã:

$(function () {
    $('a').each(function () {
        var ext = '.md';
        var href = $(this).attr('href');
        var position = href.length - ext.length;
        if (href.substring(position) === ext)
            $(this).attr('href', href.substring(0, position));
    });
});

Tôi thiết lập một kho mẫu tại CoryG89 / docsync , có trang dự án ở đây , nếu bạn muốn xem tất cả điều này hoạt động cùng nhau như thế nào.


4
Tôi đang thưởng cho bạn phần thưởng của mình vì đã đưa ra câu trả lời thấu đáo như vậy, nhưng tôi vẫn hy vọng ai đó đưa ra một giải pháp đơn giản hơn.
Matt Kantor

1
Tôi đánh giá cao điều đó Matt. Tôi sẽ tiếp tục và sử dụng 50 đại diện để đặt một khoản tiền thưởng khác với hy vọng có một giải pháp khác dễ dàng hơn / đơn giản hơn để thực hiện điều này. Giải pháp này rất hay vì nó cho phép liên kết tương đối tiếp tục hoạt động như mong đợi giữa README của bạn và các tài liệu đánh dấu khác trên trang web của bạn cũng như trong repo của bạn.
Cory Gross

1
Sẽ không dễ dàng hơn nếu chỉ tách các phần mở rộng .md trong hook post-commit? Hoặc thậm chí có thể có một cách để làm điều đó bằng cách sử dụng chính Jenkins?
jjmerelo

Tôi nghĩ rằng bạn phải giữ các tệp trong bộ nhớ với phần mở rộng .md nếu không nó sẽ không được hiển thị dưới dạng Markdown. Không phải 100% về điều đó mặc dù.
Cory Gross

2
có cái gì đơn giản hơn trong năm 2016?
Peter Krauss

5

Giải pháp của tôi cho vấn đề đồng bộ hóa README với trang Github hơi khác so với giải pháp trên. Thay vì sử dụng công cụ JavaScript Markdown riêng biệt, người ta có thể sử dụng API Github để trả về tệp Markdown được hiển thị dưới dạng HTML.

  1. Tìm nạp README.mdtừ https://api.github.com/repos/<owner>/<repo>/contents/README.md.
  2. Giải mã phản hồi Base64: window.atob( JSON.parse( blob ).content );
  3. Đăng phần đã giải mã READMElên https://api.github.com/markdowntrong phần thân JSON

     {
       "text": "<README>",
       "mode": "markdown",
       "context": "<owner>/<repo>"
     }
    
  4. Chèn HTML đã kết xuất vào một phần tử DOM, như được thực hiện bởi Brad Rhodes .

Hai lưu ý đối với cách tiếp cận này:

  1. Thực hiện hai yêu cầu nối tiếp làm chậm quá trình tải trang.
  2. Có thể gặp phải giới hạn tốc độ khi truy cập API Github.

Đối với một trang có lưu lượng truy cập thấp, nơi thời gian tải không quan trọng (~ 1-2 giây), thì phương pháp trên hoạt động đủ tốt.


atob () hoạt động tốt trong Chrome và FF nhưng không hoạt động trong IE 11. Cho biết ký tự không hợp lệ. trang web dưới joymon.github.io/joyful-visualstudio
Joy George Kunjikkuru


3

Tôi có một vài ý tưởng để chia sẻ một tệp readme duy nhất giữa trang web tài liệu của bạn và repo github chính:

  1. Bạn chỉ có thể sử dụng một nhánh gh-pages duy nhất chứa cả mã của bạn và trang web tài liệu jekyll. Kho lưu trữ của bạn có thể hơi lộn xộn và bạn sẽ cần đặt tiêu đề YAML ở đầu readme. Nó gần như hỗ trợ liên kết tương đối. Vấn đề là nếu bạn muốn jekyll hiển thị markdown của mình, nó sẽ cung cấp cho nó một phần mở rộng .html. Có thể có một cách để cấu hình điều này. Đây là một ví dụ mà tôi đã tổng hợp lại để xem nó có hoạt động không.

  2. Bạn có thể sử dụng lệnh gọi AJAX trong trang web tài liệu của mình để đọc readme từ nhánh chính của bạn, sau đó kết xuất nó bằng trình kết xuất Javascript Markdown . Điều này sẽ mất nhiều thời gian hơn để tải và nó sẽ không hỗ trợ các liên kết tương đối nếu bạn không viết một số Javascript thông minh. Nó cũng còn nhiều việc phải thực hiện hơn ý tưởng 1.


3

Một lộ trình khác cần xem xét là thiết lập hook cam kết trước để xây dựng các trang có liên quan. Tôi làm điều này trong một trong những kho của tôi . Tuy nhiên, có thể bạn sẽ phải bỏ trình tạo trang tự động và chỉ gh-pagestự mình đẩy đến chi nhánh, cũng như làm điều gì đó lạ mắt để biến tài liệu của bạn thành HTML hoặc trang web Jekyll như Nathan đề xuất .

Trong đó kho Tôi đẩy như thế này để giữ gh-pagesgiống master. Có rất nhiều cách khác để làm điều đó. Tuy nhiên, điều này có thể không lý tưởng cho tình huống của bạn (bạn có thể không muốn chúng giống hệt nhau).

Dù sao, lý do tôi đưa ra tiền thưởng cho câu hỏi này là vì tôi hy vọng ai đó có quy trình làm việc tốt hơn. Phương pháp này khá phức tạp và không linh hoạt và nó yêu cầu mọi người phải giữ các hook của họ đồng bộ.


2

Một phương pháp khác mà tôi đã làm khá thành công là sử dụng Ajax để tìm nạp tài liệu bằng cách sử dụng API Github và một công cụ đánh dấu Javascript để hiển thị HTML (cũng như được đề xuất bởi Nathan).

  1. Sử dụng Github API và JSONP để tìm nạp tài liệu từ Github
  2. Giải mã nội dung base64 trong phản hồi từ Github API
  3. Hiển thị đánh dấu bằng cách sử dụng công cụ đánh dấu javascript
  4. Hiển thị html được kết xuất

Nathan bày tỏ một số lo lắng về hiệu suất nhưng theo kinh nghiệm của tôi, nó tải dường như ngay lập tức nên tôi không nghĩ đó thực sự là một vấn đề.

Ưu điểm là dễ thiết lập và nó sẽ luôn cập nhật tài liệu của bạn ngay cả khi bạn chỉ chỉnh sửa đánh dấu trực tiếp trong trình duyệt trên github.

Tôi đã thiết lập một ví dụ trên trang Github tại http://bradrhodes.github.io/GithubDocSync/ để cho thấy nó hoạt động.


Tôi đã kết hợp phương pháp này với nhân bản để hiển thị project.wiki của mình vào các trang GitHub .
Chetabahana

2

Một khả năng khác cho phương pháp được Nathan và Brand Rhodes mô tả là sử dụng một công cụ tuyệt vời: FlatDoc do Rico Sta tạo ra. Cruz.

FlatDoc sẽ tải bằng cách truy cập tài liệu (README.md hoặc bất kỳ tệp đánh dấu nào khác), phân tích cú pháp và hiển thị với tất cả các tính năng bổ sung và thậm chí là một menu thanh bên để điều hướng!

Nó đã xây dựng trong api của mình một phương thức trợ giúp để tải các tệp từ GitHub repo master (nhưng cũng có thể tải bất kỳ nơi nào khác từ web).

Hướng dẫn

Bắt đầu với việc sao chép mẫu html sau vào index.html của bạn trong nhánh gh-pages của bạn. Tiếp tục với:

  • Thay thế "USER" bằng tên người dùng GitHub của bạn
  • Thay thế "REPO" bằng tên repo GitHub của bạn
  • Thay thế "Dự án của bạn" bằng tên dự án của bạn

Trong tập tin. Dùng thử cục bộ trong trình duyệt của bạn. Sau đó cam kết và đẩy các thay đổi. Bây giờ trang github của bạn sẽ luôn được cập nhật bằng tệp README.md trong nhánh chính của bạn.

Nếu chủ đề mặc định không phù hợp với bạn, bạn có thể tạo kiểu lại bằng css của riêng bạn.


1

Tôi cũng muốn chỉnh sửa tài liệu tổng thể và xuất bản trên các trang gh - tôi muốn cập nhật tài liệu với mã nguồn và đó có vẻ là cách tốt nhất. Đây là công việc đang được tiến hành đối với tôi, nhưng tôi đã lấy tập lệnh của Cory làm điểm bắt đầu và mở rộng nó một chút để làm cho nó hoạt động hiệu quả miễn là có một nhánh gh-pages với _layouts(tức là một trang web jekyll). Nó chuyển đổi hàng rào kiểu backtick (cho các khối mã) hoạt động tốt trong duyệt mã nguồn github, nhưng không hoạt động trong các trang gh. Tôi sử dụng một index.mdvới một bao gồm cho dự án README.mdđể tôi có thể thêm tiêu đề và một số trang trí khác. Phiên bản này cũng xử lý tài liệu trong bất kỳ thư mục lồng nhau nào được gọi là "docs" mà tôi thấy hữu ích trong một dự án có nhiều mô-đun (không phải mô-đun con git, chỉ là các thư mục con):

.git/hooks/post-commit

#!/bin/bash
###
### The following block runs after commit to "master" branch
###
if [ `git rev-parse --abbrev-ref HEAD` == "master" ]; then

    # function to convert a plain .md file to one that renders nicely in gh-pages
    function convert {
        # sed - convert links with *.md to *.html (assumed relative links in local pages)
        # awk - convert backtick fencing to highlights (script from bottom of file)
        sed -e 's/(\(.*\)\.md)/(\1.html)/g' "$1" | awk -f <(sed -e '0,/^#!.*awk/d' $0) > _temp && mv _temp "$1"
    } 

    if ! git show-ref --verify --quiet refs/heads/gh-pages; then
        echo "No gh-pages, so not syncing"
        exit 0
    fi

    # Switch to gh-pages branch to sync it with master
    ###################################################################
    git checkout gh-pages

    mkdir -p _includes

    # Sync the README.md in master to index.md adding jekyll header
    ###################################################################
    git checkout master -- README.md
    if [ -f README.md ]; then
        cp README.md _includes/
        convert _includes/README.md
        git add README.md
        git add _includes/README.md
    fi

    # Generate index if there isn't one already
    ###################################################################
    if [ ! -f index.md ]; then
        echo -e '---\ntitle: Docs\nlayout: default\n---\n\n{% include README.md %}' > index.md
        git add index.md
    fi

    # Generate a header if there isn't one already
    ###################################################################
    if [ ! -f _includes/header.txt ]; then
        echo -e '---\ntitle: Docs\nlayout: default\nhome: \n---\n\n' > _includes/header.txt
        git add _includes/header.txt
    fi

    # Sync the markdown files in all docs/* directories
    ###################################################################
    for file in `git ls-tree -r --name-only master | grep 'docs/.*\.md'`
    do
        git checkout master -- "$file"
        dir=`echo ${file%/*} | sed -e "s,[^/]*,..,g"`
        cat _includes/header.txt | sed -e "s,^home: .*$,home: ${dir}/," > _temp
        cat "$file" >> _temp && mv _temp "$file"
        convert "$file"
        git add "$file"
    done

    git commit -a -m "Sync docs from master branch to docs gh-pages directory"

    # Uncomment the following push if you want to auto push to
    # the gh-pages branch whenever you commit to master locally.
    # This is a little extreme. Use with care!
    ###################################################################
    # git push origin gh-pages

    # Finally, switch back to the master branch and exit block
    git checkout master
fi

exit $?

#!/usr/bin/awk
{
   # Replace backtick fencing (renders well when browsing github) with jekyll directives
   if (/```/) {
      IN = IN?0:1 # Are we already in a fenced section? Toggle.
      if (IN) { # If we are starting a fenced section
         if (/```\s*$/) {
           $0 = $0"text" # empty language is OK for backticks but not for jekyll
         }
         gsub(/```/, "{% highlight ")
         print $0" %}"
      } else { # ending a fenced section
        print "{% endhighlight %}" 
      }
    } else { # not a fencing line
      if (IN) { # but in a fenced section, so add indent to make sure code is rendered with <pre>
        print "    "$0
      } else {
        print
      }
    }
}

Một biến thể khác so với bản gốc là nó đặt một biến page.hometrong tất cả các trang. Điều này có thể được sử dụng để định vị đường dẫn tương đối của diractory gốc, vì vậy nó có thể được sử dụng để định vị các tài nguyên tĩnh như css. Trong _layouts/.default.htmltôi có:

<link rel="stylesheet" href="{{ page.home }}css/main.css">

Bằng cách đó, tôi có thể chỉnh sửa css, xây dựng trang web jekyll cục bộ và xem kết quả trong trình duyệt mà không cần phải đợi github xây dựng nó trên máy chủ.


0

Gần đây tôi đã tạo một gói gh-pages-maker để giải quyết vấn đề này - nó tạo trang web nhiều trang bằng cách sử dụng nhiều tệp MD và một tệp cấu hình.

Nó cập nhật chính xác tất cả các liên kết giữa các trang. Tương đối dễ dàng biến nó thành một phần của CI để cam kết các thay đổi trở lại nhánh gh-pages.

Tôi đang sử dụng nó ở đâyở đây .


0

Nó không khó , hai bản sao và dán vào thiết bị đầu cuối và bạn đã sẵn sàng.

Jekyllcho phép bạn nhập tệp đánh dấu của mình và sau đó nó sẽ đảm nhận việc chuyển đổi chúng thành HTML. Mẹo là nhập của bạn README.mdvào index.mdtệp của bạn với {% include_relative README.md %}. Đây là cách chúng tôi có thể làm điều đó:

Bạn nên tham khảo cách thiết lập một Jekylltrang web siêu đơn giản trên github (chỉ có hai tệp! )

Việc thiết lập

Bạn có thể sao chép hai tệp và để trang của bạn chạy với readme hiện tại của bạn bằng cách chỉ chạy thiết lập một lần này ( sao chép toàn bộ khối mã và pase vào thiết bị đầu cuối ):

# Copy our two files to the gh-pages branch
git checkout -b gh-pages &&
wget https://raw.githubusercontent.com/lazamar/barebones-jekyll-project-readme/master/_config.yml &&
wget https://raw.githubusercontent.com/lazamar/barebones-jekyll-project-readme/master/index.md &&
#
# Commit and publish our page on github
git add -A && git commit -m "Create project github page" &&
git push --set-upstream origin gh-pages |
#
git checkout master # go back to master branch

Tự động hóa

Sau đó, chúng ta chỉ cần tự động hóa nhiệm vụ sao chép tất cả các thay đổi từ masterđến gh-pagesnhánh trước mỗi lần đẩy. Chúng tôi có thể làm điều đó bằng cách chạy tập lệnh này ( bạn có thể sao chép và dán nó vào thiết bị đầu cuối )

$(cat > .git/hooks/pre-push << EOF
#!/bin/sh
we_are_in_gh_pages="\$(git branch | grep -G "* gh-pages")"

if [ ! "\$we_are_in_gh_pages" ];
  then
    git checkout gh-pages &&
    git rebase master &&
    git push -f &&
    git checkout master # go back to master branch
fi
EOF
) && chmod 775 .git/hooks/pre-push

Nó sẽ tạo ra một push hook sẽ sao chép tất cả các thay đổi từ masternhánh đến gh-pagesmỗi khi bạn chạygit push .

Đó là nó. Làm xong.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.