Tim Dennis
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- title: Open Refine Exercises spellcheck: true authors: ["Belinda Weaver", "Tim Dennis", "Library Carpentry community"] tags: openrefine, data, munging --- ## Library Carpentry - Open Refine Exercises ### Exercise 1: Download data: * Go to <https://raw.githubusercontent.com/data-lessons/library-openrefine/gh-pages/data/doaj-article-sample.csv>. Right click anywhere on the screen and choose `Save As …` The filename is `doaj-article-sample.csv` and it should be saved to Desktop. ### Exercise 2: Create project 1. Open OpenRefine. 2. Click `Create project` then `Choose File`. Select `doaj-article-sample.csv` and then click Next. In the Parse text section, ensure separators are commas and first line is being parsed as a header. Then click `Create project`. ### Exercise 2 (Alternate): Create project from web address 1. Open OpenRefine: typically located here: <http://127.0.0.1:3333> 2. Click `Create Project` and then `Web Addresses (URLs)` 3. Paste in <https://raw.githubusercontent.com/data-lessons/library-openrefine/gh-pages/data/doaj-article-sample.csv>. In the Parse text section, ensure separators are commas and first line is being parsed as a header. Then click `Create project`. ### Split author names into separate cells 1. To work with the author names effectively we need to split them into separate cells: 2. Click the dropdown menu at the top of the `Author` column 3. Choose `Edit cells ->Split multi-valued cells` 4. In the prompt type the “:” symbol and click `OK` 5. Note that the rows are still numbered sequentially 6. Click the `Records` option to change to `Records` mode and then go back to `Rows` 7. Note how the numbering changes as you toggle - indicating that several rows are related to the same record. * A common workflow with multi-valued cells is split multi-valued cells into individual cells (what we did above), * then modify/refine/clean individual cells * join multi-valued cells back together We'll cover modifying cells will be covered in future episode, but for now we will cover how to join cells back together that have been split previously. ### Join authors back together * Click the dropdown menu at the top of the Author column * Choose `Edit cells->Join multi-valued cells` * In the prompt type the ( | ) symbol * Here we are specifying the delimiter character for OpenRefine to use to join the values together. * Click `OK` to join the Authors cells back together You will now see that split rows have gone away - the Authors have been joined into a single cell with the specified delimiter. Our Rows and Records values will now be the same since we do not have any more split columns. Click both the Rows and Records options and observe how the numbers of Rows and Records are equal ### Class exercise: <https://librarycarpentry.github.io/lc-open-refine/03-working-with-data/index.html#splitting-subjects-into-separate-cells> ## Faceting * ‘Facet’ groups all the values that appear in a column, and then allow you to filter the data by these values and edit values across many records at the same time. * text facet is simplest * The facet consists of a list of values used in the data. You can filter the data displayed by clicking on one of these headings. * We can `include` facet values or `exclude` and `invert` * Let's look at this in action ### Publisher - faceting demo 1. Click on the drop down menu at the top of the `publisher` column and choose `Facet > Text Facet`. The facet will then appear in the left hand panel 2. Filter by facet by clicking or include 3. Select multiple values to include 4. You can `invert` your selections to exclude 5. Include a value and then look at top to `invert inclusion`. ### Class Exercise: Which licences are used for articles in this file? 1. Create a `Facet -> Text facet` for the `Licence` column 2. What is the most common Licence in the file? 3. How many articles in the file don’t have a licence assigned? ### Class Exercise: Find all publications without a DOI * Use the `Facet -> Facet by blank` function to find all publications in this data set without a DOI ### Exercise 5: Correct the Language values via a facet 1. Create a `Facet -> Text facet` on the Language column * Notice that there is both ‘EN’ and ‘English’ 2. Put the mouse over the `English` value 3. Click `Edit` 4. Type `EN` and click `Apply` ### Exercise 6: Replacing text 1. People often want to replace text. This is done via a GREL `value.replace` transform. 2. Click the dropdown menu at the top of the `Author` column 3. Choose `Edit cells -> Transform`. 4. In the Expression box, type `value.replace("|", ":")` 5. You will see how the change will look in the box below. If you are happy, click OK. 6. This will replace the pipe separator with a colon. Use the same syntax (e.g. `value.replace()` to replace words, punctuation and so on. ### Exercise 8: Use Clustering to clean up author data 1. Choose `Edit cells -> Cluster and edit...` from the `Author` column (which should already be split into individual values from the last exercise) 1. Using the `key collision` method with the `fingerprint` Keying Function work through the clusters of values, merging them to a single value where appropriate 1. Try changing the clustering method being used - which ones work well? ## Working with columns ### Reorder columns * You can re-order the columns by clicking the drop-down menu at the top of the first column (labelled ‘All’), and choosing `Edit columns->Re-order / remove columns` ### Sort * sort data in OpenRefine by clicking on the drop-down menu for the column you want to sort on, and choosing Sort. * Once you have sorted the data, a new Sort drop-down menu will be displayed. * Unlike in Excel, ‘Sorts’ in OpenRefine are temporary - that is, if you remove the Sort, the data will go back to its original ‘unordered’ state. The ‘Sort’ drop-down menu lets you amend the existing sort (e.g., reverse the sort order), remove existing sorts, and/or make sorts permanent. ## Introduction to Transformations in OpenRefine - **Purpose of Transformations:** - Used when facets, filters, and clusters can't standardize or modify data. - **Examples of Data Transformations:** - **Splitting Columns:** Break data in one column into multiple (e.g., split an address into street, city, state). - **Standardizing Formats:** Format data without altering its values (e.g., remove punctuation or standardize date formats). - **Extracting Data:** Pull specific information from a text string (e.g., extract an ISBN from a citation). - **Transformations in OpenRefine:** - Written in **GREL** (General Refine Expression Language). - Similar to Excel formulas, but mainly for text manipulation rather than numerical operations. - GREL documentation link for reference: [GREL Documentation](https://docs.openrefine.org/manual/grelfunctions). | Common Transformation | Action | GREL Expression | |--------------------------------------------|--------------------------------------------------------------------------------------------------------|-----------------------| | Trim leading and trailing whitespace | Removes any ‘whitespace’ characters (e.g. spaces, tabs) from the start and end of the current value | `value.trim()` | | To titlecase | Converts the current value to titlecase (i.e. each word starts with an uppercase character) | `value.toTitlecase()` | | To uppercase | Converts the current value to uppercase | `value.toUppercase()` | | To lowercase | Converts the current value to lowercase | `value.toLowercase()` | ## Correct Publisher data 1. Create a `text facet` on the Publisher column 2. Note that in the values there are two that look almost identical - why do these two values appear separately rather than as a single value? if you know share in chat. 3. On the publisher column use the dropdown menu to select `Edit cells->Common transforms->Collapse consecutive whitespace` 4. Look at the publisher facet now - has it changed? (if it hasn't changed try clicking the `Refresh` option to make sure it updates) ## Writing transformations - **Where to Write GREL Expressions:** - Select the column to transform. - Choose `Edit cells → Transform…`. - A new screen opens with an 'Expression' box for entering your transformation. - **Preview:** The effect of the transformation on the first 10 rows of your data is shown immediately. - **Default Expression:** - The default value is `value`, which means no change will occur. This represents the current value in the selected column. - **GREL Syntax:** - Two types of syntax can be used interchangeably: 1. `value.function(options)` 2. `function(value, options)` - Both work the same way; it’s a matter of personal preference. - **Additional Preview Options:** - **History:** View previous transformations and reuse or star them. - **Starred:** Access starred transformations for quick reference. - **Help:** View a list of all GREL functions with a brief explanation. ### Example Transformation: Title Case - **Goal:** Use facets and GREL to convert text in the 'Title' column to Title Case. --- ## Put titles into Title Case Use Facets and the GREL expression `value.toTitlecase()` to put the titles in Title Case 1. Facet by publisher 2. Select "Akshantala Enterprises" and "Society of Pharmaceutical Technocrats" 3. To select multiple values in the facet use the `include` link that appears to the right of the facet 4. See that the Titles for these are all in uppercase 5. Click the dropdown menu on the Title column 6. Choose `Edit cells->Transform...` 7. In the Expression box type `value.toTitlecase()` 8. In the Preview pane under value.toTitlecase() you can see what the effect of running this will be 9. Click `OK` 10. Find examples of titles that are still not correct, or have been incorrectly cased (abbreviations, species names, etc.) ### keypoints - You can alter data in OpenRefine based on specific instructions - You can preview the results of your GREL expression ## Undo/Redo - **Undo/Redo Features:** - OpenRefine allows you to **undo** or **redo** any steps you've taken in the data cleaning process. - These features give you flexibility to experiment with transformations and easily reverse changes if necessary. - **Accessing Undo/Redo:** - The Undo/Redo options are located in the **left-hand panel**. - The panel shows a list of all steps taken so far. - **How Undo Works:** - Click on the last step you want to preserve, and all steps after that will be undone automatically. - Greyed-out steps in the list can be reapplied by clicking on the last step you want to restore. - **Important Considerations:** - If you undo steps and then perform new transformations, the greyed-out steps will disappear, and you will no longer be able to redo them. - **Saving and Reapplying Steps:** - Use the **Extract** button to save steps as a JSON file, which can be shared or reused in different projects. - To reapply steps, use the **Apply** button and paste the JSON file into the project. - In OpenRefine version 3.6.0 or later, you can also directly save the JSON via the **Export** button. - **Undo/Redo Data is Saved:** - Undo/Redo history is saved automatically with the project, so you can pick up where you left off when reopening the project. ### Key Points: - Undo/Redo helps retrace your steps and undo changes. - You can save and reapply steps using the **Extract** and **Apply** features. ## Transforming Strings, Numbers, Dates, and Booleans ### Data Types: - **Importance of Understanding Data Types:** - Knowing data types helps in writing effective transformations using GREL. - **Data Types in OpenRefine:** - **String:** A piece of text (most common type). - **Number:** Numeric data. - **Date:** Date data, necessary for date-related functions. - **Boolean:** Binary values (true/false). - **Array:** Covered in the next lesson. --- ### Dates and Numbers: - **String Representation:** - Often, dates and numbers may be treated as strings in OpenRefine. - **Need for Conversion:** - Some operations (e.g., sorting) require converting these values to their appropriate types (Date or Number). --- ### Reformatting Dates: 1. **Prepare the Data:** - Remove all facets and filters. 2. **Transform the Date Column:** - Select `Edit cells → Transform`. - Enter the expression: `value.toDate("dd/MM/yyyy")`. 3. **Check the Output:** - Values should display in green, adhering to ISO 8601 format. 4. **Create a New Formatted Column:** - Select `Edit column → Add column based on this column`. - Name the new column "Formatted-Date". - Enter the expression: `value.toString("dd MMMM yyyy")`. --- ### Specifying Date Formatting in GREL Expressions: - **Using Pattern Strings:** - GREL allows specifying date and time formats through case-sensitive pattern strings. #### Date and Time Pattern Representation: | Letter | Date or Time Representation | |--------|-----------------------------| | `y` | Year | | `M` | Month in year | | `D` | Day in year | | `d` | Day in month | | `F` | Day of week in month | | `E` | Day name in week | | `u` | Day number of week | | `a` | AM/PM marker | #### Examples of Date Patterns: | Date and Time Pattern Input | Output | |------------------------------|---------------------------| | `"yyyy-MM-dd"` | 2022-06-05 | | `"dd MMM yyyy"` | 05 Jun 2022 | | `"EEE, MMM d, ''yy"` | Mon, Jun 5, '22 | | `"yyyy.MMMM.dd hh:mm a"` | 2022.June.05 12:10 PM | | `"EEE, d MMM yyyy HH:mm:ss"` | Mon, 5 Jun 2022 12:10:10 | --- ### Booleans: - **Definition:** - A Boolean is a binary value: **true** or **false**. ### Exercise: Find Reversed Author Names 1. **Split Author Names:** - Ensure author names are split into individual cells using `Edit cells → Split multi-valued cells`. 2. **Create a Custom Text Facet:** - Select `Facet → Custom text facet...`. 3. **Write GREL for Faceting:** - In the Expression box, type: `value.contains(",")`. - Click `OK`. 4. **Review Results:** - The facet should show 'true' for values containing a comma (indicating reversed names) and 'false' for others. ### Key Points: - You can alter data in OpenRefine based on specific instructions. - Expand data editing functions by building your own - transformations. --- ## Transformations - Handling Arrays ### Preview: - Example: Transforming a list with duplicated values into a unique list using arrays. --- ### Using Arrays in Transformations: - **Function:** `uniques()` removes duplicates from an array. - **Example Subject Column:** - Original: `crystal structure|clozapinium|crystal structure|molecular configuration|hydrogen bonding|supramolecular assembly|Chemistry|QD1-999` - Goal: Remove duplicates. #### GREL Transformation Steps: 1. **Split the String into an Array:** - `value.split("|")` → `["crystal structure", "clozapinium", "crystal structure", ...]` 2. **Remove Duplicates:** - `uniques()` → `["crystal structure", "clozapinium", "molecular configuration", ...]` 3. **Join the Array Back to a String:** - `join("|")` → `crystal structure|clozapinium|molecular configuration|...` --- ### Understanding Arrays: - **Definition:** - An Array is a data type that contains a list of values. - **Example Arrays:** - Strings: `["crystal structure", "clozapinium", ...]` - Numbers: `[1, 2, 3, 4]` - ![list](https://hackmd.io/_uploads/SJPR-eiaR.png) - **Key Operations:** - Arrays can be sorted, de-duplicated, and manipulated in GREL. - Cannot be stored directly in OpenRefine cells. --- ### Recap on Best Practices for Separators: - Avoid using separator characters already present in the text. - Discuss implications of choosing inappropriate separators. --- ### Exercise: Reverse Author Names 1. **Prerequisite:** Ensure author names are split into individual cells using `Edit cells → Split multi-valued cells`. 2. **Create Custom Text Facet:** - On the Authors column, select `Facet → Custom text facet...`. - In the Expression box, type: `value.contains(",")`. 3. **Review the Facet:** - Click `OK`. You should see 'true' for names with a comma. 4. **Narrow Down Results:** - Select 'true' to focus on reversed author names. 5. **Transform Author Names:** - On the Authors column, select `Edit cells → Transform`. - In the Expression box, type: `value.split(", ")`. 6. **Reverse and Join:** - Update the expression to: `value.split(", ").reverse().join(" ")`. 7. **Preview Changes:** - Verify that the transformation reverses the names to personal name first order. 8. **Apply Changes:** - Click `OK`. --- ### Key Points: - Arrays cannot appear directly in an OpenRefine cell. - Arrays can be used in many ways with GREL expressions. ## Exporting Data ### Objectives: - Explain how to export data in different formats from OpenRefine. ### Key Questions: - How do I export data from OpenRefine? --- ### Note about OpenRefine: - Edits made in OpenRefine are stored within the program and do not affect your original file. - OpenRefine uses "import" and "export" to describe moving data in and out of the interface. - To save your work in a viewable format, you need to export your data. --- ### Exporting Data: - After working with a dataset, you may wish to export it. - Access the export options via the **Export** button at the top right of the OpenRefine interface. #### Available Export Formats: - **HTML** - **Excel** - **CSV (Comma-Separated Values)** - **TSV (Tab-Separated Values)** - **Custom Exports:** - Export specific fields. - Add headers or footers. - Specify the format exactly. --- ### Exporting a Portion of Your Data: - Use facets or filters to select specific rows to export. - The resulting file will only include the selected rows. #### Important Note: - Be cautious not to accidentally export only a portion of your data. - Check the top left of the interface to ensure all rows are being displayed for a full export. --- ### Key Points: - You can export your data in a variety of formats. ## Looking Up Data ### Looking Up Data from a URL: - OpenRefine can retrieve data from URLs for additional information. - Example: Look up names against the **Virtual International Authority File (VIAF)** to retrieve details like birth/death dates and identifiers. #### Two-Step Process: 1. **Retrieve Data:** Use the dropdown menu on a column to select `Edit column → Add column by fetching URLs`. - Enter a GREL expression to create a URL based on existing data. 2. **Extract Relevant Information:** Use OpenRefine functions like: - `parseHtml()` - `parseJson()` --- We are going to query the CrossRef API https://www.crossref.org/ >CrossRef is a nonprofit organization that assigns Digital Object Identifiers (DOIs) to scholarly content, ensuring permanent access and discoverability. It helps publishers, institutions, and researchers by linking citations and maintaining up-to-date content metadata across the academic ecosystem. It has an API: https://api.crossref.org/journals/ and we can query it with our issn (a unique number for journals). ### Challenge: Retrieving Journal Details from CrossRef via ISSN 1. **Select a Single Row:** - Click the star icon for the row containing an ISSN. - Facet by Star to choose the row. 2. **Fetch URLs:** - In the ISSN column, select `Edit column → Add column by fetching URLs`. - Name the new column (e.g., "Journal_details"). - Write GREL to create the URL: ```grel "https://api.crossref.org/journals/"+value ``` - Click 'OK' and wait for data to be fetched. 3. **Parse JSON Data:** - In the new column, select `Edit column → Add column based on this column`. - Name the new column (e.g., "Journal_title"). - Enter the expression: ```grel value.parseJson().message.title ``` - Click 'OK' to extract the journal title. --- ### Reconciliation Services: - Reconciliation services allow you to look up terms in your data against external services. - This method is often quicker and more sophisticated than fetching data from URLs. - To use the Reconciliation function, the external resource must support it. #### Example: Using VIAF Virtual International Authority File Reconciliation Service 1. **Start Reconciliation:** - In the Publisher column, select `Reconcile → Start Reconciling`. - Add the service details: - Public service: `https://refine.codefork.com/reconcile/viaf` - Local service: `http://localhost:8080/reconcile/viaf` 2. **Select Entity Type:** - Choose "Corporate Name" for the entity type. 3. **Match Candidates:** - Uncheck "Auto-match candidates with high confidence". (This can be a time saver, but in this case you are going to uncheck it, so you can see the results before a match is made) - Click 'Start Reconciling'. - Review matches in the Publisher column. 4. **Accept Matches:** - Use the 'tick' or 'double tick' options to accept matches. - Use `Reconcile → Actions → Match each cell to its best candidate` for bulk matching. 5. **Extract VIAF ID:** - In the Publisher column, select `Edit column → Add column based on this column`. - Name the new column "VIAF-ID". - Use the expression: ```grel cell.recon.match.id ``` --- ### Using the ‘cross' Function: - The `cross` function allows you to look up data in other OpenRefine projects on the same computer. - It returns an array of matching rows, enabling data comparisons between projects. --- ### Extensions: - OpenRefine functionality can be enhanced by installing extensions. - A list of available extensions can be found at [OpenRefine Extensions](http://openrefine.org/extensions). --- ### Key Points: - OpenRefine can look up custom URLs to fetch data based on project content. - API calls can be custom-built or utilize existing Reconciliation services. - OpenRefine can be further enhanced by installing extensions.

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully